Browse code

Netmgmt: update set_duid to support multi network interface

Change-Id: I2f225efb3aa535c9ffb02dae647ebc8c8e31ac21
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/6130
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Dheeraj S Shetty <dheerajs@vmware.com>

michellew-vmware authored on 2018/11/08 09:26:07
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,874 @@
0
+--- netmgmt-1.0.4-orig/common/defines.h	2016-07-28 12:22:38.000000000 -0700
1
+@@ -20,3 +20,6 @@
2
+           goto error; \
3
+        } \
4
+     } while(0)
5
++
6
++#define IS_VALID_INTERFACE_NAME(_pstr) \
7
++    ((_pstr) && (*_pstr) && (strnlen(_pstr, IFNAMSIZ) < IFNAMSIZ))
8
+--- netmgmt-1.0.4-orig/common/includes.h	2016-07-28 12:22:38.000000000 -0700
9
+@@ -17,6 +17,8 @@
10
+ #include <stdint.h>
11
+ #include <string.h>
12
+ #include <errno.h>
13
++#include <stdarg.h>
14
++#include <regex.h>
15
+ 
16
+ #include "defines.h"
17
+ #include "prototypes.h"
18
+--- netmgmt-1.0.4-orig/common/memory.c	2016-07-28 12:22:38.000000000 -0700
19
+@@ -140,6 +140,64 @@
20
+     goto cleanup;
21
+ }
22
+ 
23
++uint32_t
24
++netmgr_alloc_string_printf(
25
++    char** ppszDst,
26
++    const char* pszFmt,
27
++    ...
28
++    )
29
++{
30
++    uint32_t err = 0;
31
++    size_t nSize = 0;
32
++    char* pszDst = NULL;
33
++    char chDstTest = '\0';
34
++    va_list argList;
35
++
36
++    if (!ppszDst || !pszFmt)
37
++    {
38
++        err = EINVAL;
39
++        bail_on_error(err);
40
++    }
41
++
42
++    //Find size
43
++    va_start(argList, pszFmt);
44
++    nSize = vsnprintf(&chDstTest, 1, pszFmt, argList);
45
++    va_end(argList);
46
++
47
++    if (nSize <= 0)
48
++    {
49
++        err = errno;
50
++        bail_on_error(err);
51
++    }
52
++    nSize = nSize + 1;
53
++
54
++    err = netmgr_alloc(nSize, (void**)&pszDst);
55
++    bail_on_error(err);
56
++
57
++    va_start(argList, pszFmt);
58
++    nSize = vsnprintf(pszDst, nSize, pszFmt, argList);
59
++    va_end(argList);
60
++
61
++    if (nSize <= 0)
62
++    {
63
++        err = errno;
64
++        bail_on_error(err);
65
++    }
66
++    *ppszDst = pszDst;
67
++
68
++cleanup:
69
++    return err;
70
++
71
++error:
72
++    if (ppszDst)
73
++    {
74
++        *ppszDst = NULL;
75
++    }
76
++    netmgr_free(pszDst);
77
++    goto cleanup;
78
++}
79
++
80
++
81
+ void
82
+ netmgr_free(
83
+     void* pMemory
84
+--- netmgmt-1.0.4-orig/common/prototypes.h	2016-07-28 12:22:38.000000000 -0700
85
+@@ -14,6 +14,8 @@
86
+ 
87
+ // memory.c
88
+ 
89
++#define IS_NULL_OR_EMPTY(_pstr)  (!(_pstr) || !(*(_pstr)))
90
++
91
+ uint32_t
92
+ netmgr_alloc(
93
+     size_t size,
94
+@@ -38,3 +40,9 @@
95
+     void* pMemory
96
+     );
97
+ 
98
++uint32_t
99
++netmgr_alloc_string_printf(
100
++    char** ppszDst,
101
++    const char* pszFmt,
102
++    ...
103
++    );
104
+--- netmgmt-1.0.4-orig/include/public/netmgr.h	2016-07-28 12:22:38.000000000 -0700
105
+@@ -15,6 +15,27 @@
106
+ #ifndef __NETMGR_H__
107
+ #define __NETMGR_H__
108
+ 
109
++/*
110
++ * Error codes
111
++ */
112
++#define NM_BASE_ERROR                          4096U
113
++#define NM_ERR_INVALID_PARAMETER               (NM_BASE_ERROR + 1)
114
++#define NM_ERR_NOT_SUPPORTED                   (NM_BASE_ERROR + 2)
115
++#define NM_ERR_OUT_OF_MEMORY                   (NM_BASE_ERROR + 3)
116
++#define NM_ERR_VALUE_NOT_FOUND                 (NM_BASE_ERROR + 4)
117
++#define NM_ERR_VALUE_EXISTS                    (NM_BASE_ERROR + 5)
118
++#define NM_ERR_INVALID_INTERFACE               (NM_BASE_ERROR + 6)
119
++#define NM_ERR_INVALID_ADDRESS                 (NM_BASE_ERROR + 7)
120
++#define NM_ERR_INVALID_MODE                    (NM_BASE_ERROR + 8)
121
++#define NM_ERR_BAD_CONFIG_FILE                 (NM_BASE_ERROR + 9)
122
++#define NM_ERR_WRITE_FAILED                    (NM_BASE_ERROR + 10)
123
++#define NM_ERR_TIME_OUT                        (NM_BASE_ERROR + 11)
124
++#define NM_ERR_DHCP_TIME_OUT                   (NM_BASE_ERROR + 12)
125
++#define NM_MAX_ERROR                           (NM_BASE_ERROR + 100)
126
++
127
++/*
128
++ * Interface configuration structs
129
++ */
130
+ typedef struct _NETMGR_INTERFACE
131
+ {
132
+     char* pszName;
133
+--- netmgmt-1.0.4-orig/src/defines.h	2016-07-28 12:22:38.000000000 -0700
134
+@@ -26,13 +26,14 @@
135
+ #define SECTION_RESOLVE                "Resolve"
136
+ #define SECTION_NETWORK                "Network"
137
+ #define SECTION_DHCP                   "DHCP"
138
++#define SECTION_MATCH                  "Match"
139
+ 
140
+ #define KEY_IAID                       "IAID"
141
+ #define KEY_DUID_TYPE                  "DUIDType"
142
+ #define KEY_DUID_RAWDATA               "DUIDRawData"
143
+ #define KEY_DNS                        "DNS"
144
+ #define KEY_USE_DNS                    "UseDNS"
145
+-
146
++#define KEY_NAME                       "Name"
147
+ 
148
+ #define bail_on_error(errcode) \
149
+     do { \
150
+--- netmgmt-1.0.4-orig/src/includes.h	2016-07-28 12:22:38.000000000 -0700
151
+@@ -26,6 +26,7 @@
152
+ #include <iniparser.h>
153
+ 
154
+ #include "../common/prototypes.h"
155
++#include "../common/includes.h"
156
+ #include "defines.h"
157
+ #include "structs.h"
158
+ #include "prototypes.h"
159
+--- netmgmt-1.0.4-orig/src/netmgr.c	2016-07-28 12:22:38.000000000 -0700
160
+@@ -14,11 +14,308 @@
161
+ 
162
+ #include "includes.h"
163
+ 
164
++static uint32_t
165
++nm_regex_match_ifname(
166
++    const char *pszIfName,
167
++    const char *pszMatchName
168
++)
169
++{
170
++    uint32_t err = 0;
171
++    regex_t rx;
172
++    regmatch_t rm;
173
++    size_t patternLen, ifNameLen, n;
174
++    char *q, *pszPattern = NULL;
175
++    const char *p;
176
++
177
++    if (!IS_VALID_INTERFACE_NAME(pszIfName) ||
178
++        !IS_VALID_INTERFACE_NAME(pszMatchName))
179
++    {
180
++        err = NM_ERR_INVALID_INTERFACE;
181
++        bail_on_error(err);
182
++    }
183
++
184
++    ifNameLen = strlen(pszIfName);
185
++    patternLen = strlen(pszMatchName);
186
++    for (p = strchr(pszMatchName, '*'), n = 0; p; p = strchr(++p, '*'), n++);
187
++
188
++    err = netmgr_alloc(patternLen + n + 1, (void **)&pszPattern);
189
++    bail_on_error(err);
190
++
191
++    for (p = pszMatchName, q = pszPattern; *p; p++, q++)
192
++    {
193
++        if (*p == '*')
194
++        {
195
++            *q++ = '.';
196
++        }
197
++        *q = *p;
198
++    }
199
++
200
++    err = regcomp(&rx, pszPattern, 0);
201
++    bail_on_error(err);
202
++
203
++    err = regexec(&rx, pszIfName, 1, &rm, 0);
204
++    bail_on_error(err);
205
++    if ((rm.rm_eo - rm.rm_so) < ifNameLen)
206
++    {
207
++        err = NM_ERR_VALUE_NOT_FOUND;
208
++        bail_on_error(err);
209
++    }
210
++cleanup:
211
++    netmgr_free(pszPattern);
212
++    regfree(&rx);
213
++    return err;
214
++error:
215
++    goto cleanup;
216
++}
217
++
218
++static uint32_t
219
++nm_alloc_conf_filename(
220
++    char **ppszFilename,
221
++    const char *pszPath,
222
++    const char *pszFname
223
++)
224
++{
225
++    uint32_t err = 0;
226
++    size_t len = 0;
227
++    char *pszFilename = NULL;
228
++
229
++    if (!ppszFilename || !pszPath || !pszFname)
230
++    {
231
++        err = NM_ERR_INVALID_PARAMETER;
232
++        bail_on_error(err);
233
++    }
234
++
235
++    len = strlen(pszPath) + strlen (pszFname) + 1;
236
++    err = netmgr_alloc(len, (void **)&pszFilename);
237
++    bail_on_error(err);
238
++
239
++    sprintf(pszFilename, "%s%s", pszPath, pszFname);
240
++
241
++    *ppszFilename = pszFilename;
242
++
243
++cleanup:
244
++    return err;
245
++error:
246
++    netmgr_free(pszFilename);
247
++    if (ppszFilename != NULL)
248
++    {
249
++        *ppszFilename = NULL;
250
++    }
251
++    goto cleanup;
252
++}
253
++
254
++static uint32_t
255
++nm_get_network_conf_filename_match(
256
++    const char *pszIfName,
257
++    char **ppszFilename,
258
++    size_t *pMatchLen
259
++)
260
++{
261
++    uint32_t err = 0;
262
++    size_t matchLen = 0;
263
++    struct dirent *hFile;
264
++    DIR *dirFile = NULL;
265
++    char *p, *pszFileName = NULL, *pszMatchName = NULL, *pszCfgFileName = NULL;
266
++
267
++    dirFile = opendir(SYSTEMD_NET_PATH);
268
++    if (dirFile == NULL)
269
++    {
270
++        err = errno;
271
++        bail_on_error(err);
272
++    }
273
++
274
++    // TODO: Looks fine but closely vet this logic with systemd
275
++    errno = 0;
276
++    while ((hFile = readdir(dirFile)) != NULL)
277
++    {
278
++        if (!strcmp(hFile->d_name, ".")) continue;
279
++        if (!strcmp(hFile->d_name, "..")) continue;
280
++        if (hFile->d_name[0] == '.') continue;
281
++        if ((((p = strstr(hFile->d_name, ".network")) != NULL) &&
282
++             (strlen(p) == strlen(".network"))) ||
283
++            (((p = strstr(hFile->d_name, ".network.manual")) != NULL) &&
284
++             (strlen(p) == strlen(".network.manual"))))
285
++        {
286
++            err = nm_alloc_conf_filename(&pszFileName,
287
++                                         SYSTEMD_NET_PATH,
288
++                                         hFile->d_name);
289
++            bail_on_error(err);
290
++           err = nm_get_key_value(pszFileName,
291
++                                   SECTION_MATCH,
292
++                                   KEY_NAME,
293
++                                   &pszMatchName);
294
++            if ((err == NM_ERR_VALUE_NOT_FOUND) ||
295
++                (err == NM_ERR_BAD_CONFIG_FILE))
296
++            {
297
++                /* Ignore cfg file with invalid/missing Match section */
298
++                err = 0;
299
++            }
300
++            bail_on_error(err);
301
++
302
++            if (pszMatchName && !nm_regex_match_ifname(pszIfName, pszMatchName))
303
++            {
304
++                if (pszCfgFileName == NULL)
305
++                {
306
++                    pszCfgFileName = pszFileName;
307
++                    matchLen = strlen(pszMatchName);
308
++                    pszFileName = NULL;
309
++                    continue;
310
++                }
311
++                if (strcmp(pszCfgFileName, pszFileName) > 0)
312
++                {
313
++                    netmgr_free(pszCfgFileName);
314
++                    pszCfgFileName = pszFileName;
315
++                    matchLen = strlen(pszMatchName);
316
++                    pszFileName = NULL;
317
++                }
318
++            }
319
++
320
++            netmgr_free(pszMatchName);
321
++            pszMatchName = NULL;
322
++            netmgr_free(pszFileName);
323
++            pszFileName = NULL;
324
++        }
325
++    }
326
++
327
++    if (!pszCfgFileName)
328
++    {
329
++        err = NM_ERR_VALUE_NOT_FOUND;
330
++        bail_on_error(err);
331
++    }
332
++
333
++    *ppszFilename = pszCfgFileName;
334
++    if (pMatchLen)
335
++    {
336
++        *pMatchLen = matchLen;
337
++    }
338
++
339
++cleanup:
340
++    if (dirFile != NULL)
341
++    {
342
++        closedir(dirFile);
343
++    }
344
++    netmgr_free(pszMatchName);
345
++    netmgr_free(pszFileName);
346
++    return err;
347
++
348
++error:
349
++    if (ppszFilename)
350
++    {
351
++        *ppszFilename = NULL;
352
++    }
353
++    if (pMatchLen)
354
++    {
355
++        *pMatchLen = 0;
356
++    }
357
++    netmgr_free(pszCfgFileName);
358
++    goto cleanup;
359
++}
360
++
361
++static uint32_t
362
++nm_get_network_conf_filename_for_update(
363
++    const char *pszIfName,
364
++    char **ppszFilename
365
++)
366
++{
367
++    uint32_t err = 0;
368
++    size_t ifNameLen, matchLen = 0;
369
++    char fName[IFNAMSIZ+strlen(SYSTEMD_NET_PATH)+strlen("00-.network")+1];
370
++    char *pszFilename = NULL, *pszNewFilename = NULL, *pszCmd = NULL;
371
++
372
++    err = nm_get_network_conf_filename_match(pszIfName, &pszFilename, &matchLen);
373
++    if (err == NM_ERR_VALUE_NOT_FOUND)
374
++    {
375
++        err = 0;
376
++    }
377
++    bail_on_error(err);
378
++
379
++    ifNameLen = strlen(pszIfName);
380
++    if ((pszFilename == NULL) || (matchLen < ifNameLen))
381
++    {
382
++        sprintf(fName, "%s00-%s.network", SYSTEMD_NET_PATH, pszIfName);
383
++        if (access(fName, F_OK) == 0)
384
++        {
385
++            /* Designated conf file for this interface exists with bad match */
386
++            err = NM_ERR_BAD_CONFIG_FILE;
387
++            bail_on_error(err);
388
++        }
389
++
390
++        err = netmgr_alloc_string(fName, &pszNewFilename);
391
++        bail_on_error(err);
392
++
393
++        /* Create dedicated conf for interface based on best match conf file */
394
++        if (pszFilename != NULL)
395
++        {
396
++            err = netmgr_alloc_string_printf(&pszCmd,
397
++                                             "/usr/bin/cp -f -p %s %s",
398
++                                             pszFilename,
399
++                                             pszNewFilename);
400
++            bail_on_error(err);
401
++
402
++            err = nm_run_command(pszCmd);
403
++            bail_on_error(err);
404
++        }
405
++
406
++        err = nm_set_key_value(pszNewFilename,
407
++                               SECTION_MATCH,
408
++                               KEY_NAME,
409
++                               pszIfName,
410
++                               F_CREATE_CFG_FILE);
411
++        bail_on_error(err);
412
++    }
413
++    else
414
++    {
415
++        err = netmgr_alloc_string(pszFilename, &pszNewFilename);
416
++        bail_on_error(err);
417
++    }
418
++
419
++    *ppszFilename = pszNewFilename;
420
++
421
++cleanup:
422
++    netmgr_free(pszFilename);
423
++    netmgr_free(pszCmd);
424
++    return err;
425
++
426
++error:
427
++    if (ppszFilename)
428
++    {
429
++        *ppszFilename = NULL;
430
++    }
431
++    netmgr_free(pszNewFilename);
432
++    goto cleanup;
433
++}
434
++
435
++static uint32_t
436
++nm_get_network_conf_filename(
437
++    const char *pszIfName,
438
++    char **ppszFilename)
439
++{
440
++    return nm_get_network_conf_filename_match(pszIfName, ppszFilename, NULL);
441
++}
442
++
443
++/*
444
++ * Service management APIs
445
++ */
446
++uint32_t
447
++nm_restart_network_service()
448
++{
449
++    uint32_t err = 0;
450
++    const char command[] = "systemctl restart systemd-networkd";
451
++
452
++    err = nm_run_command(command);
453
++    bail_on_error(err);
454
++
455
++clean:
456
++    return err;
457
++error:
458
++    goto clean;
459
++}
460
++
461
+ uint32_t
462
+ enum_interfaces(
463
+     int nFamily,
464
+     PNETMGR_INTERFACE* ppInterfaces
465
+-    )
466
++)
467
+ {
468
+     uint32_t err = 0;
469
+     int fd = 0;
470
+@@ -836,30 +1133,31 @@
471
+ )
472
+ {
473
+     uint32_t err = 0;
474
+-    char cfgFileName[MAX_LINE];
475
++    char *pszCfgFileName = NULL;
476
+     const char *duidType;
477
+     uint16_t n1, n2;
478
+     char szDuid[MAX_LINE];
479
+ 
480
+-    if (pszInterfaceName != NULL)
481
++    if (!pszInterfaceName)
482
+     {
483
+-        /* TODO: Add support */
484
+-        err = ENOTSUP;
485
+-        bail_on_error(err);
486
++        err = EINVAL;
487
+     }
488
+     else
489
+     {
490
+-        sprintf(cfgFileName, "%snetworkd.conf", SYSTEMD_PATH);
491
++       err = nm_get_network_conf_filename_for_update(pszInterfaceName,
492
++                                                     &pszCfgFileName);
493
+     }
494
++    bail_on_error(err);
495
+ 
496
+     if ((pszDuid == NULL) || (strlen(pszDuid) == 0))
497
+     {
498
+-        err = set_key_value(cfgFileName, SECTION_DHCP, KEY_DUID_TYPE, NULL,
499
++        err = set_key_value(pszCfgFileName, SECTION_DHCP, KEY_DUID_TYPE, NULL,
500
+                             F_CREATE_CFG_FILE);
501
+         bail_on_error(err);
502
+ 
503
+-        err = set_key_value(cfgFileName, SECTION_DHCP, KEY_DUID_RAWDATA, NULL,
504
++        err = set_key_value(pszCfgFileName, SECTION_DHCP, KEY_DUID_RAWDATA, NULL,
505
+                             F_CREATE_CFG_FILE);
506
++        bail_on_error(err);
507
+     }
508
+     else
509
+     {
510
+@@ -877,16 +1175,19 @@
511
+         }
512
+         /* TODO: Validate DUID length and DUID bytes */
513
+ 
514
+-        err = set_key_value(cfgFileName, SECTION_DHCP, KEY_DUID_TYPE, duidType,
515
++        err = set_key_value(pszCfgFileName, SECTION_DHCP, KEY_DUID_TYPE, duidType,
516
+                             F_CREATE_CFG_FILE);
517
+         bail_on_error(err);
518
+ 
519
+-        err = set_key_value(cfgFileName, SECTION_DHCP, KEY_DUID_RAWDATA, szDuid,
520
++        err = set_key_value(pszCfgFileName, SECTION_DHCP, KEY_DUID_RAWDATA, szDuid,
521
+                             F_CREATE_CFG_FILE);
522
++        bail_on_error(err);
523
+     }
524
++    err = nm_restart_network_service();
525
+     bail_on_error(err);
526
+ 
527
+ error:
528
++    netmgr_free(pszCfgFileName);
529
+     return err;
530
+ }
531
+ 
532
+@@ -897,7 +1198,7 @@
533
+ )
534
+ {
535
+     uint32_t err = 0;
536
+-    char cfgFileName[MAX_LINE];
537
++    char *pszCfgFileName = NULL;
538
+     uint16_t duidType;
539
+     char *pszDuidType = NULL;
540
+     char *pszDuid = NULL;
541
+@@ -908,18 +1209,17 @@
542
+         bail_on_error(err);
543
+     }
544
+ 
545
+-    if (pszInterfaceName != NULL)
546
++    if (pszInterfaceName == NULL)
547
+     {
548
+-        /* TODO: Add support */
549
+-        err = ENOTSUP;
550
+-        bail_on_error(err);
551
++        err = EINVAL;
552
+     }
553
+     else
554
+     {
555
+-        sprintf(cfgFileName, "%snetworkd.conf", SYSTEMD_PATH);
556
++        err = nm_get_network_conf_filename(pszInterfaceName, &pszCfgFileName);
557
+     }
558
++    bail_on_error(err);
559
+ 
560
+-    err = get_key_value(cfgFileName, SECTION_DHCP, KEY_DUID_TYPE, &pszDuidType);
561
++    err = get_key_value(pszCfgFileName, SECTION_DHCP, KEY_DUID_TYPE, &pszDuidType);
562
+     bail_on_error(err);
563
+ 
564
+     duidType = duid_type_from_strtype(pszDuidType);
565
+@@ -929,7 +1229,7 @@
566
+         bail_on_error(err);
567
+     }
568
+ 
569
+-    err = get_key_value(cfgFileName, SECTION_DHCP, KEY_DUID_RAWDATA, &pszDuid);
570
++    err = get_key_value(pszCfgFileName, SECTION_DHCP, KEY_DUID_RAWDATA, &pszDuid);
571
+     bail_on_error(err);
572
+ 
573
+     err = netmgr_alloc((strlen(pszDuid) + 8), (void *)ppszDuid);
574
+@@ -945,6 +1245,7 @@
575
+     {
576
+         netmgr_free(pszDuidType);
577
+     }
578
++    netmgr_free(pszCfgFileName);
579
+     return err;
580
+ 
581
+ error:
582
+--- netmgmt-1.0.4-orig/src/utils.c	2016-07-28 12:22:38.000000000 -0700
583
+@@ -169,3 +169,200 @@
584
+     return err;
585
+ }
586
+ 
587
++uint32_t
588
++nm_run_command(
589
++    const char *pszCommand
590
++)
591
++{
592
++    uint32_t err = 0;
593
++    FILE *pipe_fp = NULL;
594
++
595
++    if (pszCommand == NULL)
596
++    {
597
++        err = NM_ERR_INVALID_PARAMETER;
598
++        bail_on_error(err);
599
++    }
600
++
601
++    pipe_fp = popen(pszCommand, "r");
602
++    if (pipe_fp == NULL)
603
++    {
604
++        err = errno;
605
++        bail_on_error(err);
606
++    }
607
++
608
++clean:
609
++    if (pipe_fp != NULL)
610
++    {
611
++        if (pclose(pipe_fp) == -1)
612
++        {
613
++            err = errno;
614
++        }
615
++    }
616
++    return err;
617
++error:
618
++    goto clean;
619
++}
620
++
621
++uint32_t
622
++nm_get_key_value(
623
++    const char *pszConfigFileName,
624
++    const char *pszSection,
625
++    const char *pszKey,
626
++    char **ppszValue
627
++)
628
++{
629
++    uint32_t err = 0, dwNumSections = 0;
630
++    PCONFIG_INI pConfig = NULL;
631
++    PSECTION_INI *ppSections = NULL, pSection = NULL;
632
++    PKEYVALUE_INI pKeyValue = NULL;
633
++    *ppszValue = NULL;
634
++
635
++    if (IS_NULL_OR_EMPTY(pszConfigFileName) || IS_NULL_OR_EMPTY(pszSection) ||
636
++        IS_NULL_OR_EMPTY(pszKey))
637
++    {
638
++        err = NM_ERR_INVALID_PARAMETER;
639
++        bail_on_error(err);
640
++    }
641
++
642
++    err = ini_cfg_read(pszConfigFileName, &pConfig);
643
++    bail_on_error(err);
644
++
645
++    err = ini_cfg_find_sections(pConfig, pszSection, &ppSections, &dwNumSections);
646
++    bail_on_error(err);
647
++
648
++    if (dwNumSections > 1)
649
++    {
650
++        /* TODO: Log error */
651
++        err = NM_ERR_BAD_CONFIG_FILE;
652
++        bail_on_error(err);
653
++    }
654
++    else if (dwNumSections == 0)
655
++    {
656
++        err = NM_ERR_VALUE_NOT_FOUND;
657
++        bail_on_error(err);
658
++    }
659
++
660
++    pSection = ppSections[0];
661
++
662
++    pKeyValue = ini_cfg_find_key(pSection, pszKey);
663
++    if (pKeyValue == NULL)
664
++    {
665
++        err = NM_ERR_VALUE_NOT_FOUND;
666
++        bail_on_error(err);
667
++    }
668
++    /* malloc return memory - caller to free */
669
++    err = netmgr_alloc_string(pKeyValue->pszValue, ppszValue);
670
++
671
++error:
672
++    if (ppSections != NULL)
673
++    {
674
++        ini_cfg_free_sections(ppSections, dwNumSections);
675
++    }
676
++    if (pConfig != NULL)
677
++    {
678
++        ini_cfg_free_config(pConfig);
679
++    }
680
++    return err;
681
++}
682
++
683
++uint32_t
684
++nm_set_key_value(
685
++    const char *pszConfigFileName,
686
++    const char *pszSection,
687
++    const char *pszKey,
688
++    const char *pszValue,
689
++    uint32_t flags
690
++)
691
++{
692
++    uint32_t err = 0, dwNumSections = 0;
693
++    PCONFIG_INI pConfig = NULL;
694
++    PSECTION_INI *ppSections = NULL, pSection = NULL;
695
++    PKEYVALUE_INI pKeyValue = NULL;
696
++    FILE *fp;
697
++
698
++    if (IS_NULL_OR_EMPTY(pszConfigFileName) || IS_NULL_OR_EMPTY(pszSection) ||
699
++        IS_NULL_OR_EMPTY(pszKey))
700
++    {
701
++        err = NM_ERR_INVALID_PARAMETER;
702
++        bail_on_error(err);
703
++    }
704
++
705
++    if (TEST_FLAG(flags, F_CREATE_CFG_FILE))
706
++    {
707
++        /* 'touch' the file if it does't exist */
708
++        if ((fp = fopen(pszConfigFileName, "a+")) != NULL)
709
++        {
710
++            fclose(fp);
711
++        }
712
++        else
713
++        {
714
++            err = errno;
715
++            bail_on_error(err);
716
++        }
717
++    }
718
++
719
++    err = ini_cfg_read(pszConfigFileName, &pConfig);
720
++    bail_on_error(err);
721
++
722
++    err = ini_cfg_find_sections(pConfig, pszSection, &ppSections, &dwNumSections);
723
++    bail_on_error(err);
724
++
725
++    if (dwNumSections > 1)
726
++    {
727
++        err = NM_ERR_BAD_CONFIG_FILE;
728
++        bail_on_error(err);
729
++    }
730
++    else if (dwNumSections == 0)
731
++    {
732
++        if (pszValue != NULL)
733
++        {
734
++            err = ini_cfg_add_section(pConfig, pszSection, &pSection);
735
++            bail_on_error(err);
736
++        }
737
++        else
738
++        {
739
++            /* Bug out with success - nothing to set, no section found. */
740
++            err = 0;
741
++            goto error;
742
++        }
743
++    }
744
++    else
745
++    {
746
++        pSection = ppSections[0];
747
++    }
748
++
749
++    pKeyValue = ini_cfg_find_key(pSection, pszKey);
750
++    if (pKeyValue == NULL)
751
++    {
752
++        if (pszValue != NULL)
753
++        {
754
++            err = ini_cfg_add_key(pSection, pszKey, pszValue);
755
++        }
756
++    }
757
++    else
758
++    {
759
++        if (pszValue != NULL)
760
++        {
761
++            err = ini_cfg_set_value(pSection, pszKey, pszValue);
762
++        }
763
++        else
764
++        {
765
++            err = ini_cfg_delete_key(pSection, pszKey);
766
++        }
767
++    }
768
++    bail_on_error(err);
769
++
770
++    err = ini_cfg_save(pszConfigFileName, pConfig);
771
++    bail_on_error(err);
772
++
773
++error:
774
++    if (ppSections != NULL)
775
++    {
776
++        ini_cfg_free_sections(ppSections, dwNumSections);
777
++    }
778
++    if (pConfig != NULL)
779
++    {
780
++        ini_cfg_free_config(pConfig);
781
++    }
782
++    return err;
783
++}
784
+--- netmgmt-1.0.4-orig/src/utils.h	2016-07-28 12:22:38.000000000 -0700
785
+@@ -34,4 +34,26 @@
786
+     char **ppszValue
787
+ );
788
+ 
789
++uint32_t
790
++nm_get_key_value(
791
++    const char *pszConfigFileName,
792
++    const char *pszSection,
793
++    const char *pszKey,
794
++    char **ppszValue
795
++);
796
++
797
++uint32_t
798
++nm_set_key_value(
799
++    const char *pszConfigFileName,
800
++    const char *pszSection,
801
++    const char *pszKey,
802
++    const char *pszValue,
803
++    uint32_t flags
804
++);
805
++
806
++uint32_t
807
++nm_run_command(
808
++    const char *pszCommand
809
++);
810
++
811
+ #endif /* __UTILS_H__ */
812
+--- netmgmt-1.0.4-orig/tools/netmgr/main.c	2016-07-28 12:22:38.000000000 -0700
813
+@@ -362,13 +362,13 @@
814
+         bail_on_error(err);
815
+     }
816
+ 
817
+-    if(pCmdArgs->nCmdCount < 2)
818
++    if(pCmdArgs->nCmdCount < 3)
819
+     {
820
+         err = EDOM;
821
+         bail_on_error(err);
822
+     }
823
+ 
824
+-    err = set_duid(NULL, pCmdArgs->ppszCmds[1]);
825
++    err = set_duid(pCmdArgs->ppszCmds[1], pCmdArgs->ppszCmds[2]);
826
+     bail_on_error(err);
827
+ 
828
+ cleanup:
829
+@@ -379,7 +379,7 @@
830
+     {
831
+         fprintf(
832
+                stderr,
833
+-               "Usage: set_duid <duid>\n");
834
++               "Usage: set_duid <ifname> <duid>\n");
835
+     }
836
+     goto cleanup;
837
+ }
838
+@@ -398,13 +398,13 @@
839
+         bail_on_error(err);
840
+     }
841
+ 
842
+-    if(pCmdArgs->nCmdCount < 1)
843
++    if(pCmdArgs->nCmdCount < 2)
844
+     {
845
+         err = EDOM;
846
+         bail_on_error(err);
847
+     }
848
+ 
849
+-    err = get_duid(NULL, &duid);
850
++    err = get_duid(pCmdArgs->ppszCmds[1], &duid);
851
+     bail_on_error(err);
852
+ 
853
+     fprintf(stdout, "DUID=%s\n", duid);
854
+@@ -421,7 +421,7 @@
855
+     {
856
+         fprintf(
857
+                stderr,
858
+-               "Usage: get_duid\n");
859
++               "Usage: get_duid <ifname> \n");
860
+     }
861
+     goto cleanup;
862
+ }
... ...
@@ -1,7 +1,7 @@
1 1
 Summary:       PhotonOS Network Management Utilities
2 2
 Name:          netmgmt
3 3
 Version:       1.0.4
4
-Release:       3%{?dist}
4
+Release:       4%{?dist}
5 5
 Group:         Applications/System
6 6
 Vendor:        VMware, Inc.
7 7
 License:       Apache2.0
... ...
@@ -9,6 +9,7 @@ URL:           http://www.vmware.com
9 9
 Source0:       %{name}-%{version}.tar.gz
10 10
 Patch0:        netmgmt-v104-dns-buffer-overrun-fix.patch
11 11
 Patch1:        netmgmt-v104-allow-multiple-keys.patch
12
+Patch2:        netmgmt-set-duid-fix.patch
12 13
 Distribution:  Photon
13 14
 BuildRequires: autoconf
14 15
 BuildRequires: glib-devel
... ...
@@ -25,12 +26,13 @@ Group: Development/Libraries
25 25
 Requires: netmgmt = %{version}-%{release}
26 26
 
27 27
 %description devel
28
-header files and libraries for netmgmt 
28
+header files and libraries for netmgmt
29 29
 
30 30
 %prep
31 31
 %setup -q
32 32
 %patch0 -p1
33 33
 %patch1 -p1
34
+%patch2 -p1
34 35
 
35 36
 %build
36 37
 autoreconf -mif
... ...
@@ -62,6 +64,8 @@ find %{buildroot} -name '*.la' -delete
62 62
 # %doc ChangeLog README COPYING
63 63
 
64 64
 %changelog
65
+*       Wed Nov 7 2018 Michelle Wang <michellew@vmware.com> 1.0.4-4
66
+-       Fix set_duid for multi interface.
65 67
 *	Thu  Oct 27 2016 Vinay Kulkarni <kulkarniv@vmware.com> 1.0.4-3
66 68
 -	Fix to allow reading multiple keys in a config section.
67 69
 *	Tue  Aug 16 2016 Vinay Kulkarni <kulkarniv@vmware.com> 1.0.4-2