1 /*
2 * interface_conf.c: interfaces XML handling
3 *
4 * Copyright (C) 2006-2010, 2013-2015 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21 #include <config.h>
22 #include "virerror.h"
23 #include "datatypes.h"
24
25 #include "interface_conf.h"
26
27 #include "viralloc.h"
28 #include "virxml.h"
29 #include "viruuid.h"
30 #include "virbuffer.h"
31 #include "virstring.h"
32
33 #define VIR_FROM_THIS VIR_FROM_INTERFACE
34
35 VIR_ENUM_IMPL(virInterface,
36 VIR_INTERFACE_TYPE_LAST,
37 "ethernet", "bridge", "bond", "vlan",
38 );
39
40 static virInterfaceDef *
41 virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType);
42
43 static int
44 virInterfaceDefDevFormat(virBuffer *buf, const virInterfaceDef *def,
45 virInterfaceType parentIfType);
46
47 static void
virInterfaceIPDefFree(virInterfaceIPDef * def)48 virInterfaceIPDefFree(virInterfaceIPDef *def)
49 {
50 if (def == NULL)
51 return;
52 g_free(def->address);
53 g_free(def);
54 }
55
56
57 static void
virInterfaceProtocolDefFree(virInterfaceProtocolDef * def)58 virInterfaceProtocolDefFree(virInterfaceProtocolDef *def)
59 {
60 size_t i;
61
62 if (def == NULL)
63 return;
64 for (i = 0; i < def->nips; i++)
65 virInterfaceIPDefFree(def->ips[i]);
66 g_free(def->ips);
67 g_free(def->family);
68 g_free(def->gateway);
69 g_free(def);
70 }
71
72
73 void
virInterfaceDefFree(virInterfaceDef * def)74 virInterfaceDefFree(virInterfaceDef *def)
75 {
76 size_t i;
77 int pp;
78
79 if (def == NULL)
80 return;
81
82 g_free(def->name);
83 g_free(def->mac);
84
85 switch (def->type) {
86 case VIR_INTERFACE_TYPE_BRIDGE:
87 g_free(def->data.bridge.delay);
88 for (i = 0; i < def->data.bridge.nbItf; i++) {
89 if (def->data.bridge.itf[i] == NULL)
90 break; /* to cope with half parsed data on errors */
91 virInterfaceDefFree(def->data.bridge.itf[i]);
92 }
93 g_free(def->data.bridge.itf);
94 break;
95 case VIR_INTERFACE_TYPE_BOND:
96 g_free(def->data.bond.target);
97 for (i = 0; i < def->data.bond.nbItf; i++) {
98 if (def->data.bond.itf[i] == NULL)
99 break; /* to cope with half parsed data on errors */
100 virInterfaceDefFree(def->data.bond.itf[i]);
101 }
102 g_free(def->data.bond.itf);
103 break;
104 case VIR_INTERFACE_TYPE_VLAN:
105 g_free(def->data.vlan.tag);
106 g_free(def->data.vlan.dev_name);
107 break;
108 }
109
110 /* free all protos */
111 for (pp = 0; pp < def->nprotos; pp++)
112 virInterfaceProtocolDefFree(def->protos[pp]);
113 g_free(def->protos);
114 g_free(def);
115 }
116
117
118 static int
virInterfaceDefParseName(virInterfaceDef * def,xmlXPathContextPtr ctxt)119 virInterfaceDefParseName(virInterfaceDef *def,
120 xmlXPathContextPtr ctxt)
121 {
122 char *tmp;
123
124 tmp = virXPathString("string(./@name)", ctxt);
125 if (tmp == NULL) {
126 virReportError(VIR_ERR_XML_ERROR,
127 "%s", _("interface has no name"));
128 return -1;
129 }
130 def->name = tmp;
131 return 0;
132 }
133
134
135 static int
virInterfaceDefParseMtu(virInterfaceDef * def,xmlXPathContextPtr ctxt)136 virInterfaceDefParseMtu(virInterfaceDef *def,
137 xmlXPathContextPtr ctxt)
138 {
139 unsigned long mtu;
140 int ret;
141
142 ret = virXPathULong("string(./mtu/@size)", ctxt, &mtu);
143 if ((ret == -2) || ((ret == 0) && (mtu > 100000))) {
144 virReportError(VIR_ERR_XML_ERROR,
145 "%s", _("interface mtu value is improper"));
146 return -1;
147 } else if (ret == 0) {
148 def->mtu = (unsigned int) mtu;
149 }
150 return 0;
151 }
152
153
154 static int
virInterfaceDefParseStartMode(virInterfaceDef * def,xmlXPathContextPtr ctxt)155 virInterfaceDefParseStartMode(virInterfaceDef *def,
156 xmlXPathContextPtr ctxt)
157 {
158 char *tmp;
159
160 tmp = virXPathString("string(./start/@mode)", ctxt);
161 if (tmp == NULL) {
162 def->startmode = VIR_INTERFACE_START_UNSPECIFIED;
163 } else if (STREQ(tmp, "onboot")) {
164 def->startmode = VIR_INTERFACE_START_ONBOOT;
165 } else if (STREQ(tmp, "hotplug")) {
166 def->startmode = VIR_INTERFACE_START_HOTPLUG;
167 } else if (STREQ(tmp, "none")) {
168 def->startmode = VIR_INTERFACE_START_NONE;
169 } else {
170 virReportError(VIR_ERR_XML_ERROR,
171 _("unknown interface startmode %s"), tmp);
172 VIR_FREE(tmp);
173 return -1;
174 }
175 VIR_FREE(tmp);
176 return 0;
177 }
178
179
180 static int
virInterfaceDefParseBondMode(xmlXPathContextPtr ctxt)181 virInterfaceDefParseBondMode(xmlXPathContextPtr ctxt)
182 {
183 char *tmp;
184 int ret = 0;
185
186 tmp = virXPathString("string(./@mode)", ctxt);
187 if (tmp == NULL)
188 return VIR_INTERFACE_BOND_NONE;
189 if (STREQ(tmp, "balance-rr")) {
190 ret = VIR_INTERFACE_BOND_BALRR;
191 } else if (STREQ(tmp, "active-backup")) {
192 ret = VIR_INTERFACE_BOND_ABACKUP;
193 } else if (STREQ(tmp, "balance-xor")) {
194 ret = VIR_INTERFACE_BOND_BALXOR;
195 } else if (STREQ(tmp, "broadcast")) {
196 ret = VIR_INTERFACE_BOND_BCAST;
197 } else if (STREQ(tmp, "802.3ad")) {
198 ret = VIR_INTERFACE_BOND_8023AD;
199 } else if (STREQ(tmp, "balance-tlb")) {
200 ret = VIR_INTERFACE_BOND_BALTLB;
201 } else if (STREQ(tmp, "balance-alb")) {
202 ret = VIR_INTERFACE_BOND_BALALB;
203 } else {
204 virReportError(VIR_ERR_XML_ERROR,
205 _("unknown bonding mode %s"), tmp);
206 ret = -1;
207 }
208 VIR_FREE(tmp);
209 return ret;
210 }
211
212
213 static int
virInterfaceDefParseBondMiiCarrier(xmlXPathContextPtr ctxt)214 virInterfaceDefParseBondMiiCarrier(xmlXPathContextPtr ctxt)
215 {
216 char *tmp;
217 int ret = 0;
218
219 tmp = virXPathString("string(./miimon/@carrier)", ctxt);
220 if (tmp == NULL)
221 return VIR_INTERFACE_BOND_MII_NONE;
222 if (STREQ(tmp, "ioctl")) {
223 ret = VIR_INTERFACE_BOND_MII_IOCTL;
224 } else if (STREQ(tmp, "netif")) {
225 ret = VIR_INTERFACE_BOND_MII_NETIF;
226 } else {
227 virReportError(VIR_ERR_XML_ERROR,
228 _("unknown mii bonding carrier %s"), tmp);
229 ret = -1;
230 }
231 VIR_FREE(tmp);
232 return ret;
233 }
234
235
236 static int
virInterfaceDefParseBondArpValid(xmlXPathContextPtr ctxt)237 virInterfaceDefParseBondArpValid(xmlXPathContextPtr ctxt)
238 {
239 char *tmp;
240 int ret = 0;
241
242 tmp = virXPathString("string(./arpmon/@validate)", ctxt);
243 if (tmp == NULL)
244 return VIR_INTERFACE_BOND_ARP_NONE;
245 if (STREQ(tmp, "active")) {
246 ret = VIR_INTERFACE_BOND_ARP_ACTIVE;
247 } else if (STREQ(tmp, "backup")) {
248 ret = VIR_INTERFACE_BOND_ARP_BACKUP;
249 } else if (STREQ(tmp, "all")) {
250 ret = VIR_INTERFACE_BOND_ARP_ALL;
251 } else {
252 virReportError(VIR_ERR_XML_ERROR,
253 _("unknown arp bonding validate %s"), tmp);
254 ret = -1;
255 }
256 VIR_FREE(tmp);
257 return ret;
258 }
259
260
261 static int
virInterfaceDefParseDhcp(virInterfaceProtocolDef * def,xmlNodePtr dhcp,xmlXPathContextPtr ctxt)262 virInterfaceDefParseDhcp(virInterfaceProtocolDef *def,
263 xmlNodePtr dhcp, xmlXPathContextPtr ctxt)
264 {
265 VIR_XPATH_NODE_AUTORESTORE(ctxt)
266 char *tmp;
267 int ret = 0;
268
269 def->dhcp = 1;
270 ctxt->node = dhcp;
271 def->peerdns = -1;
272 /* Not much to do in the current version */
273 tmp = virXPathString("string(./@peerdns)", ctxt);
274 if (tmp) {
275 bool state = false;
276 if (virStringParseYesNo(tmp, &state) < 0) {
277 virReportError(VIR_ERR_XML_ERROR,
278 _("unknown dhcp peerdns value %s"), tmp);
279 ret = -1;
280 } else {
281 def->peerdns = state ? 1 : 0;
282 }
283 VIR_FREE(tmp);
284 }
285
286 return ret;
287 }
288
289
290 static int
virInterfaceDefParseIP(virInterfaceIPDef * def,xmlXPathContextPtr ctxt)291 virInterfaceDefParseIP(virInterfaceIPDef *def,
292 xmlXPathContextPtr ctxt)
293 {
294 int ret = 0;
295 char *tmp;
296 long l;
297
298 tmp = virXPathString("string(./@address)", ctxt);
299 def->address = tmp;
300 if (tmp != NULL) {
301 ret = virXPathLong("string(./@prefix)", ctxt, &l);
302 if (ret == 0) {
303 def->prefix = (int) l;
304 } else if (ret == -2) {
305 virReportError(VIR_ERR_XML_ERROR,
306 "%s", _("Invalid ip address prefix value"));
307 return -1;
308 }
309 }
310
311 return 0;
312 }
313
314
315 static int
virInterfaceDefParseProtoIPv4(virInterfaceProtocolDef * def,xmlXPathContextPtr ctxt)316 virInterfaceDefParseProtoIPv4(virInterfaceProtocolDef *def,
317 xmlXPathContextPtr ctxt)
318 {
319 xmlNodePtr dhcp;
320 xmlNodePtr *ipNodes = NULL;
321 int nipNodes, ret = -1;
322 size_t i;
323 char *tmp;
324
325 tmp = virXPathString("string(./route[1]/@gateway)", ctxt);
326 def->gateway = tmp;
327
328 dhcp = virXPathNode("./dhcp", ctxt);
329 if (dhcp != NULL) {
330 if (virInterfaceDefParseDhcp(def, dhcp, ctxt) < 0)
331 return -1;
332 }
333
334 nipNodes = virXPathNodeSet("./ip", ctxt, &ipNodes);
335 if (nipNodes < 0)
336 return -1;
337 if (ipNodes == NULL)
338 return 0;
339
340 def->ips = g_new0(virInterfaceIPDef *, nipNodes);
341
342 def->nips = 0;
343 for (i = 0; i < nipNodes; i++) {
344
345 virInterfaceIPDef *ip;
346
347 ip = g_new0(virInterfaceIPDef, 1);
348
349 ctxt->node = ipNodes[i];
350 if (virInterfaceDefParseIP(ip, ctxt) < 0) {
351 virInterfaceIPDefFree(ip);
352 goto error;
353 }
354 def->ips[def->nips++] = ip;
355 }
356
357 ret = 0;
358
359 error:
360 VIR_FREE(ipNodes);
361 return ret;
362 }
363
364
365 static int
virInterfaceDefParseProtoIPv6(virInterfaceProtocolDef * def,xmlXPathContextPtr ctxt)366 virInterfaceDefParseProtoIPv6(virInterfaceProtocolDef *def,
367 xmlXPathContextPtr ctxt)
368 {
369 xmlNodePtr dhcp, autoconf;
370 xmlNodePtr *ipNodes = NULL;
371 int nipNodes, ret = -1;
372 size_t i;
373 char *tmp;
374
375 tmp = virXPathString("string(./route[1]/@gateway)", ctxt);
376 def->gateway = tmp;
377
378 autoconf = virXPathNode("./autoconf", ctxt);
379 if (autoconf != NULL)
380 def->autoconf = 1;
381
382 dhcp = virXPathNode("./dhcp", ctxt);
383 if (dhcp != NULL) {
384 if (virInterfaceDefParseDhcp(def, dhcp, ctxt) < 0)
385 return -1;
386 }
387
388 nipNodes = virXPathNodeSet("./ip", ctxt, &ipNodes);
389 if (nipNodes < 0)
390 return -1;
391 if (ipNodes == NULL)
392 return 0;
393
394 def->ips = g_new0(virInterfaceIPDef *, nipNodes);
395
396 def->nips = 0;
397 for (i = 0; i < nipNodes; i++) {
398
399 virInterfaceIPDef *ip;
400
401 ip = g_new0(virInterfaceIPDef, 1);
402
403 ctxt->node = ipNodes[i];
404 if (virInterfaceDefParseIP(ip, ctxt) < 0) {
405 virInterfaceIPDefFree(ip);
406 goto error;
407 }
408 def->ips[def->nips++] = ip;
409 }
410
411 ret = 0;
412
413 error:
414 VIR_FREE(ipNodes);
415 return ret;
416 }
417
418
419 static int
virInterfaceDefParseIfAdressing(virInterfaceDef * def,xmlXPathContextPtr ctxt)420 virInterfaceDefParseIfAdressing(virInterfaceDef *def,
421 xmlXPathContextPtr ctxt)
422 {
423 VIR_XPATH_NODE_AUTORESTORE(ctxt)
424 xmlNodePtr *protoNodes = NULL;
425 int nProtoNodes, pp, ret = -1;
426 char *tmp;
427
428 nProtoNodes = virXPathNodeSet("./protocol", ctxt, &protoNodes);
429 if (nProtoNodes < 0)
430 goto error;
431
432 if (nProtoNodes == 0) {
433 /* no protocols is an acceptable outcome */
434 return 0;
435 }
436
437 def->protos = g_new0(virInterfaceProtocolDef *, nProtoNodes);
438
439 def->nprotos = 0;
440 for (pp = 0; pp < nProtoNodes; pp++) {
441
442 virInterfaceProtocolDef *proto;
443
444 proto = g_new0(virInterfaceProtocolDef, 1);
445
446 ctxt->node = protoNodes[pp];
447 tmp = virXPathString("string(./@family)", ctxt);
448 if (tmp == NULL) {
449 virReportError(VIR_ERR_XML_ERROR,
450 "%s", _("protocol misses the family attribute"));
451 virInterfaceProtocolDefFree(proto);
452 goto error;
453 }
454 proto->family = tmp;
455 if (STREQ(tmp, "ipv4")) {
456 ret = virInterfaceDefParseProtoIPv4(proto, ctxt);
457 if (ret != 0) {
458 virInterfaceProtocolDefFree(proto);
459 goto error;
460 }
461 } else if (STREQ(tmp, "ipv6")) {
462 ret = virInterfaceDefParseProtoIPv6(proto, ctxt);
463 if (ret != 0) {
464 virInterfaceProtocolDefFree(proto);
465 goto error;
466 }
467 } else {
468 virReportError(VIR_ERR_XML_ERROR,
469 _("unsupported protocol family '%s'"), tmp);
470 virInterfaceProtocolDefFree(proto);
471 goto error;
472 }
473 def->protos[def->nprotos++] = proto;
474 }
475
476 ret = 0;
477
478 error:
479 VIR_FREE(protoNodes);
480 return ret;
481
482 }
483
484
485 static int
virInterfaceDefParseBridge(virInterfaceDef * def,xmlXPathContextPtr ctxt)486 virInterfaceDefParseBridge(virInterfaceDef *def,
487 xmlXPathContextPtr ctxt)
488 {
489 xmlNodePtr *interfaces = NULL;
490 xmlNodePtr bridge;
491 virInterfaceDef *itf;
492 char *tmp = NULL;
493 int nbItf;
494 size_t i;
495 int ret = 0;
496
497 bridge = ctxt->node;
498 def->data.bridge.stp = -1;
499 if ((tmp = virXMLPropString(bridge, "stp"))) {
500 if (STREQ(tmp, "on")) {
501 def->data.bridge.stp = 1;
502 } else if (STREQ(tmp, "off")) {
503 def->data.bridge.stp = 0;
504 } else {
505 virReportError(VIR_ERR_XML_ERROR,
506 _("bridge interface stp should be on or off got %s"),
507 tmp);
508 goto error;
509 }
510 }
511 def->data.bridge.delay = virXMLPropString(bridge, "delay");
512
513 nbItf = virXPathNodeSet("./interface", ctxt, &interfaces);
514 if (nbItf < 0) {
515 ret = -1;
516 goto error;
517 }
518 if (nbItf > 0) {
519 def->data.bridge.itf = g_new0(struct _virInterfaceDef *, nbItf);
520 def->data.bridge.nbItf = nbItf;
521
522 for (i = 0; i < nbItf; i++) {
523 ctxt->node = interfaces[i];
524 itf = virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_BRIDGE);
525 if (itf == NULL) {
526 ret = -1;
527 def->data.bridge.nbItf = i;
528 goto error;
529 }
530 def->data.bridge.itf[i] = itf;
531 }
532 }
533
534 error:
535 VIR_FREE(tmp);
536 VIR_FREE(interfaces);
537 ctxt->node = bridge;
538 return ret;
539 }
540
541
542 static int
virInterfaceDefParseBondItfs(virInterfaceDef * def,xmlXPathContextPtr ctxt)543 virInterfaceDefParseBondItfs(virInterfaceDef *def,
544 xmlXPathContextPtr ctxt)
545 {
546 xmlNodePtr *interfaces = NULL;
547 VIR_XPATH_NODE_AUTORESTORE(ctxt)
548 virInterfaceDef *itf;
549 int nbItf;
550 size_t i;
551 int ret = -1;
552
553 nbItf = virXPathNodeSet("./interface", ctxt, &interfaces);
554 if (nbItf < 0)
555 goto cleanup;
556
557 if (nbItf == 0) {
558 ret = 0;
559 goto cleanup;
560 }
561
562 def->data.bond.itf = g_new0(struct _virInterfaceDef *, nbItf);
563
564 def->data.bond.nbItf = nbItf;
565
566 for (i = 0; i < nbItf; i++) {
567 ctxt->node = interfaces[i];
568 itf = virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_BOND);
569 if (itf == NULL) {
570 def->data.bond.nbItf = i;
571 goto cleanup;
572 }
573 def->data.bond.itf[i] = itf;
574 }
575
576 ret = 0;
577 cleanup:
578 VIR_FREE(interfaces);
579 return ret;
580 }
581
582
583 static int
virInterfaceDefParseBond(virInterfaceDef * def,xmlXPathContextPtr ctxt)584 virInterfaceDefParseBond(virInterfaceDef *def,
585 xmlXPathContextPtr ctxt)
586 {
587 int res;
588
589 def->data.bond.mode = virInterfaceDefParseBondMode(ctxt);
590 if (def->data.bond.mode < 0)
591 return -1;
592
593 if (virInterfaceDefParseBondItfs(def, ctxt) != 0)
594 return -1;
595
596 if (virXPathNode("./miimon[1]", ctxt) != NULL) {
597 def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII;
598
599 res = virXPathInt("string(./miimon/@freq)", ctxt,
600 &def->data.bond.frequency);
601 if ((res == -2) || (res == -1)) {
602 virReportError(VIR_ERR_XML_ERROR,
603 "%s", _("bond interface miimon freq missing or invalid"));
604 return -1;
605 }
606
607 res = virXPathInt("string(./miimon/@downdelay)", ctxt,
608 &def->data.bond.downdelay);
609 if (res == -2) {
610 virReportError(VIR_ERR_XML_ERROR,
611 "%s", _("bond interface miimon downdelay invalid"));
612 return -1;
613 }
614
615 res = virXPathInt("string(./miimon/@updelay)", ctxt,
616 &def->data.bond.updelay);
617 if (res == -2) {
618 virReportError(VIR_ERR_XML_ERROR,
619 "%s", _("bond interface miimon updelay invalid"));
620 return -1;
621 }
622
623 def->data.bond.carrier = virInterfaceDefParseBondMiiCarrier(ctxt);
624 if (def->data.bond.carrier < 0)
625 return -1;
626
627 } else if (virXPathNode("./arpmon[1]", ctxt) != NULL) {
628
629 def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP;
630
631 res = virXPathInt("string(./arpmon/@interval)", ctxt,
632 &def->data.bond.interval);
633 if ((res == -2) || (res == -1)) {
634 virReportError(VIR_ERR_XML_ERROR,
635 "%s", _("bond interface arpmon interval missing or invalid"));
636 return -1;
637 }
638
639 def->data.bond.target =
640 virXPathString("string(./arpmon/@target)", ctxt);
641 if (def->data.bond.target == NULL) {
642 virReportError(VIR_ERR_XML_ERROR,
643 "%s", _("bond interface arpmon target missing"));
644 return -1;
645 }
646
647 def->data.bond.validate = virInterfaceDefParseBondArpValid(ctxt);
648 if (def->data.bond.validate < 0)
649 return -1;
650 }
651
652 return 0;
653 }
654
655
656 static int
virInterfaceDefParseVlan(virInterfaceDef * def,xmlXPathContextPtr ctxt)657 virInterfaceDefParseVlan(virInterfaceDef *def,
658 xmlXPathContextPtr ctxt)
659 {
660 def->data.vlan.tag = virXPathString("string(./@tag)", ctxt);
661 if (def->data.vlan.tag == NULL) {
662 virReportError(VIR_ERR_XML_ERROR,
663 "%s", _("vlan interface misses the tag attribute"));
664 return -1;
665 }
666
667 def->data.vlan.dev_name =
668 virXPathString("string(./interface/@name)", ctxt);
669 if (def->data.vlan.dev_name == NULL) {
670 virReportError(VIR_ERR_XML_ERROR,
671 "%s", _("vlan interface misses name attribute"));
672 return -1;
673 }
674 return 0;
675 }
676
677
678 static virInterfaceDef *
virInterfaceDefParseXML(xmlXPathContextPtr ctxt,int parentIfType)679 virInterfaceDefParseXML(xmlXPathContextPtr ctxt,
680 int parentIfType)
681 {
682 g_autoptr(virInterfaceDef) def = NULL;
683 int type;
684 char *tmp;
685 VIR_XPATH_NODE_AUTORESTORE(ctxt)
686 xmlNodePtr lnk;
687
688
689 /* check @type */
690 tmp = virXPathString("string(./@type)", ctxt);
691 if (tmp == NULL) {
692 virReportError(VIR_ERR_XML_ERROR,
693 "%s", _("interface misses the type attribute"));
694 return NULL;
695 }
696 type = virInterfaceTypeFromString(tmp);
697 if (type == -1) {
698 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
699 _("unknown interface type %s"), tmp);
700 VIR_FREE(tmp);
701 return NULL;
702 }
703 VIR_FREE(tmp);
704
705 def = g_new0(virInterfaceDef, 1);
706
707 if (((parentIfType == VIR_INTERFACE_TYPE_BOND)
708 && (type != VIR_INTERFACE_TYPE_ETHERNET))
709 || ((parentIfType == VIR_INTERFACE_TYPE_BRIDGE)
710 && (type != VIR_INTERFACE_TYPE_ETHERNET)
711 && (type != VIR_INTERFACE_TYPE_BOND)
712 && (type != VIR_INTERFACE_TYPE_VLAN))
713 || (parentIfType == VIR_INTERFACE_TYPE_ETHERNET)
714 || (parentIfType == VIR_INTERFACE_TYPE_VLAN))
715 {
716 virReportError(VIR_ERR_XML_ERROR,
717 _("interface has unsupported type '%s'"),
718 virInterfaceTypeToString(type));
719 return NULL;
720 }
721 def->type = type;
722
723 if (virInterfaceDefParseName(def, ctxt) < 0)
724 return NULL;
725
726 if (parentIfType == VIR_INTERFACE_TYPE_LAST) {
727 /* only recognize these in toplevel bond interfaces */
728 if (virInterfaceDefParseStartMode(def, ctxt) < 0)
729 return NULL;
730 if (virInterfaceDefParseMtu(def, ctxt) < 0)
731 return NULL;
732 if (virInterfaceDefParseIfAdressing(def, ctxt) < 0)
733 return NULL;
734 }
735
736 if (type != VIR_INTERFACE_TYPE_BRIDGE) {
737 /* link status makes no sense for a bridge */
738 lnk = virXPathNode("./link", ctxt);
739 if (lnk && virInterfaceLinkParseXML(lnk, &def->lnk) < 0)
740 return NULL;
741 }
742
743 switch (type) {
744 case VIR_INTERFACE_TYPE_ETHERNET:
745 if ((tmp = virXPathString("string(./mac/@address)", ctxt)))
746 def->mac = tmp;
747 break;
748 case VIR_INTERFACE_TYPE_BRIDGE: {
749 xmlNodePtr bridge;
750
751 if (!(bridge = virXPathNode("./bridge[1]", ctxt))) {
752 virReportError(VIR_ERR_XML_ERROR,
753 "%s", _("bridge interface misses the bridge element"));
754 return NULL;
755 }
756 ctxt->node = bridge;
757 if (virInterfaceDefParseBridge(def, ctxt) < 0)
758 return NULL;
759 break;
760 }
761 case VIR_INTERFACE_TYPE_BOND: {
762 xmlNodePtr bond;
763
764 if (!(bond = virXPathNode("./bond[1]", ctxt))) {
765 virReportError(VIR_ERR_XML_ERROR,
766 "%s", _("bond interface misses the bond element"));
767 return NULL;
768 }
769 ctxt->node = bond;
770 if (virInterfaceDefParseBond(def, ctxt) < 0)
771 return NULL;
772 break;
773 }
774 case VIR_INTERFACE_TYPE_VLAN: {
775 xmlNodePtr vlan;
776
777 if (!(vlan = virXPathNode("./vlan[1]", ctxt))) {
778 virReportError(VIR_ERR_XML_ERROR,
779 "%s", _("vlan interface misses the vlan element"));
780 return NULL;
781 }
782 ctxt->node = vlan;
783 if (virInterfaceDefParseVlan(def, ctxt) < 0)
784 return NULL;
785 break;
786 }
787
788 }
789
790 return g_steal_pointer(&def);
791 }
792
793
794 virInterfaceDef *
virInterfaceDefParseNode(xmlDocPtr xml,xmlNodePtr root)795 virInterfaceDefParseNode(xmlDocPtr xml,
796 xmlNodePtr root)
797 {
798 g_autoptr(xmlXPathContext) ctxt = NULL;
799
800 if (!virXMLNodeNameEqual(root, "interface")) {
801 virReportError(VIR_ERR_XML_ERROR,
802 _("unexpected root element <%s>, "
803 "expecting <interface>"),
804 root->name);
805 return NULL;
806 }
807
808 if (!(ctxt = virXMLXPathContextNew(xml)))
809 return NULL;
810
811 ctxt->node = root;
812 return virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_LAST);
813 }
814
815
816 static virInterfaceDef *
virInterfaceDefParse(const char * xmlStr,const char * filename,unsigned int flags)817 virInterfaceDefParse(const char *xmlStr,
818 const char *filename,
819 unsigned int flags)
820 {
821 g_autoptr(xmlDoc) xml = NULL;
822 virInterfaceDef *def = NULL;
823
824 if ((xml = virXMLParse(filename, xmlStr, _("(interface_definition)"), "interface.rng",
825 flags & VIR_INTERFACE_DEFINE_VALIDATE))) {
826 def = virInterfaceDefParseNode(xml, xmlDocGetRootElement(xml));
827 }
828
829 return def;
830 }
831
832
833 virInterfaceDef *
virInterfaceDefParseString(const char * xmlStr,unsigned int flags)834 virInterfaceDefParseString(const char *xmlStr,
835 unsigned int flags)
836 {
837 return virInterfaceDefParse(xmlStr, NULL, flags);
838 }
839
840
841 virInterfaceDef *
virInterfaceDefParseFile(const char * filename)842 virInterfaceDefParseFile(const char *filename)
843 {
844 return virInterfaceDefParse(NULL, filename, 0);
845 }
846
847
848 static int
virInterfaceBridgeDefFormat(virBuffer * buf,const virInterfaceDef * def)849 virInterfaceBridgeDefFormat(virBuffer *buf,
850 const virInterfaceDef *def)
851 {
852 size_t i;
853 int ret = 0;
854
855 virBufferAddLit(buf, "<bridge");
856 if (def->data.bridge.stp == 1)
857 virBufferAddLit(buf, " stp='on'");
858 else if (def->data.bridge.stp == 0)
859 virBufferAddLit(buf, " stp='off'");
860 if (def->data.bridge.delay != NULL)
861 virBufferAsprintf(buf, " delay='%s'", def->data.bridge.delay);
862 virBufferAddLit(buf, ">\n");
863 virBufferAdjustIndent(buf, 2);
864
865 for (i = 0; i < def->data.bridge.nbItf; i++) {
866 if (virInterfaceDefDevFormat(buf, def->data.bridge.itf[i],
867 VIR_INTERFACE_TYPE_BRIDGE) < 0)
868 ret = -1;
869 }
870
871 virBufferAdjustIndent(buf, -2);
872 virBufferAddLit(buf, "</bridge>\n");
873 return ret;
874 }
875
876
877 static int
virInterfaceBondDefFormat(virBuffer * buf,const virInterfaceDef * def)878 virInterfaceBondDefFormat(virBuffer *buf,
879 const virInterfaceDef *def)
880 {
881 size_t i;
882 int ret = 0;
883
884 virBufferAddLit(buf, "<bond");
885 if (def->data.bond.mode == VIR_INTERFACE_BOND_BALRR)
886 virBufferAddLit(buf, " mode='balance-rr'");
887 else if (def->data.bond.mode == VIR_INTERFACE_BOND_ABACKUP)
888 virBufferAddLit(buf, " mode='active-backup'");
889 else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALXOR)
890 virBufferAddLit(buf, " mode='balance-xor'");
891 else if (def->data.bond.mode == VIR_INTERFACE_BOND_BCAST)
892 virBufferAddLit(buf, " mode='broadcast'");
893 else if (def->data.bond.mode == VIR_INTERFACE_BOND_8023AD)
894 virBufferAddLit(buf, " mode='802.3ad'");
895 else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALTLB)
896 virBufferAddLit(buf, " mode='balance-tlb'");
897 else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALALB)
898 virBufferAddLit(buf, " mode='balance-alb'");
899 virBufferAddLit(buf, ">\n");
900 virBufferAdjustIndent(buf, 2);
901
902 if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_MII) {
903 virBufferAsprintf(buf, "<miimon freq='%d'",
904 def->data.bond.frequency);
905 if (def->data.bond.downdelay > 0)
906 virBufferAsprintf(buf, " downdelay='%d'", def->data.bond.downdelay);
907 if (def->data.bond.updelay > 0)
908 virBufferAsprintf(buf, " updelay='%d'", def->data.bond.updelay);
909 if (def->data.bond.carrier == VIR_INTERFACE_BOND_MII_IOCTL)
910 virBufferAddLit(buf, " carrier='ioctl'");
911 else if (def->data.bond.carrier == VIR_INTERFACE_BOND_MII_NETIF)
912 virBufferAddLit(buf, " carrier='netif'");
913 virBufferAddLit(buf, "/>\n");
914 } else if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_ARP) {
915 if (def->data.bond.target == NULL) {
916 virReportError(VIR_ERR_INTERNAL_ERROR,
917 "%s", _("bond arp monitoring has no target"));
918 return -1;
919 }
920 virBufferAsprintf(buf, "<arpmon interval='%d' target='%s'",
921 def->data.bond.interval, def->data.bond.target);
922 if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ACTIVE)
923 virBufferAddLit(buf, " validate='active'");
924 else if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_BACKUP)
925 virBufferAddLit(buf, " validate='backup'");
926 else if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ALL)
927 virBufferAddLit(buf, " validate='all'");
928 virBufferAddLit(buf, "/>\n");
929 }
930 for (i = 0; i < def->data.bond.nbItf; i++) {
931 if (virInterfaceDefDevFormat(buf, def->data.bond.itf[i],
932 VIR_INTERFACE_TYPE_BOND) < 0)
933 ret = -1;
934 }
935
936 virBufferAdjustIndent(buf, -2);
937 virBufferAddLit(buf, "</bond>\n");
938 return ret;
939 }
940
941
942 static int
virInterfaceVlanDefFormat(virBuffer * buf,const virInterfaceDef * def)943 virInterfaceVlanDefFormat(virBuffer *buf,
944 const virInterfaceDef *def)
945 {
946 if (def->data.vlan.tag == NULL) {
947 virReportError(VIR_ERR_INTERNAL_ERROR,
948 "%s", _("vlan misses the tag name"));
949 return -1;
950 }
951
952 virBufferAsprintf(buf, "<vlan tag='%s'", def->data.vlan.tag);
953 if (def->data.vlan.dev_name != NULL) {
954 virBufferAddLit(buf, ">\n");
955 virBufferAdjustIndent(buf, 2);
956 virBufferAsprintf(buf, "<interface name='%s'/>\n",
957 def->data.vlan.dev_name);
958 virBufferAdjustIndent(buf, -2);
959 virBufferAddLit(buf, "</vlan>\n");
960 } else {
961 virBufferAddLit(buf, "/>\n");
962 }
963 return 0;
964 }
965
966
967 static int
virInterfaceProtocolDefFormat(virBuffer * buf,const virInterfaceDef * def)968 virInterfaceProtocolDefFormat(virBuffer *buf,
969 const virInterfaceDef *def)
970 {
971 size_t i, j;
972
973 for (i = 0; i < def->nprotos; i++) {
974
975 virBufferAsprintf(buf, "<protocol family='%s'>\n",
976 def->protos[i]->family);
977 virBufferAdjustIndent(buf, 2);
978
979 if (def->protos[i]->autoconf)
980 virBufferAddLit(buf, "<autoconf/>\n");
981 if (def->protos[i]->dhcp) {
982 if (def->protos[i]->peerdns == 0)
983 virBufferAddLit(buf, "<dhcp peerdns='no'/>\n");
984 else if (def->protos[i]->peerdns == 1)
985 virBufferAddLit(buf, "<dhcp peerdns='yes'/>\n");
986 else
987 virBufferAddLit(buf, "<dhcp/>\n");
988 }
989
990 for (j = 0; j < def->protos[i]->nips; j++) {
991 if (def->protos[i]->ips[j]->address != NULL) {
992
993 virBufferAsprintf(buf, "<ip address='%s'",
994 def->protos[i]->ips[j]->address);
995 if (def->protos[i]->ips[j]->prefix != 0) {
996 virBufferAsprintf(buf, " prefix='%d'",
997 def->protos[i]->ips[j]->prefix);
998 }
999 virBufferAddLit(buf, "/>\n");
1000 }
1001 }
1002 if (def->protos[i]->gateway != NULL) {
1003 virBufferAsprintf(buf, "<route gateway='%s'/>\n",
1004 def->protos[i]->gateway);
1005 }
1006
1007 virBufferAdjustIndent(buf, -2);
1008 virBufferAddLit(buf, "</protocol>\n");
1009 }
1010 return 0;
1011 }
1012
1013
1014 static int
virInterfaceStartmodeDefFormat(virBuffer * buf,virInterfaceStartMode startmode)1015 virInterfaceStartmodeDefFormat(virBuffer *buf,
1016 virInterfaceStartMode startmode)
1017 {
1018 const char *mode;
1019 switch (startmode) {
1020 case VIR_INTERFACE_START_UNSPECIFIED:
1021 return 0;
1022 case VIR_INTERFACE_START_NONE:
1023 mode = "none";
1024 break;
1025 case VIR_INTERFACE_START_ONBOOT:
1026 mode = "onboot";
1027 break;
1028 case VIR_INTERFACE_START_HOTPLUG:
1029 mode = "hotplug";
1030 break;
1031 default:
1032 virReportError(VIR_ERR_INTERNAL_ERROR,
1033 "%s", _("virInterfaceDefFormat unknown startmode"));
1034 return -1;
1035 }
1036 virBufferAsprintf(buf, "<start mode='%s'/>\n", mode);
1037 return 0;
1038 }
1039
1040
1041 static int
virInterfaceDefDevFormat(virBuffer * buf,const virInterfaceDef * def,virInterfaceType parentIfType)1042 virInterfaceDefDevFormat(virBuffer *buf,
1043 const virInterfaceDef *def,
1044 virInterfaceType parentIfType)
1045 {
1046 const char *type = NULL;
1047
1048 if (def == NULL) {
1049 virReportError(VIR_ERR_INTERNAL_ERROR,
1050 "%s", _("virInterfaceDefFormat NULL def"));
1051 return -1;
1052 }
1053
1054 if ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN)) {
1055 virReportError(VIR_ERR_INTERNAL_ERROR,
1056 "%s", _("virInterfaceDefFormat missing interface name"));
1057 return -1;
1058 }
1059
1060 if (!(type = virInterfaceTypeToString(def->type))) {
1061 virReportError(VIR_ERR_INTERNAL_ERROR,
1062 _("unexpected interface type %d"), def->type);
1063 return -1;
1064 }
1065
1066 virBufferAsprintf(buf, "<interface type='%s' ", type);
1067 if (def->name != NULL)
1068 virBufferEscapeString(buf, "name='%s'", def->name);
1069 virBufferAddLit(buf, ">\n");
1070 virBufferAdjustIndent(buf, 2);
1071
1072 if (parentIfType == VIR_INTERFACE_TYPE_LAST) {
1073 /* these elements are only valid on top-level interfaces - IP
1074 * address info ("protocol") only makes sense for the
1075 * top-level, and subordinate interfaces inherit the toplevel
1076 * setting for mtu and start mode, which cannot be overridden.
1077 */
1078 virInterfaceStartmodeDefFormat(buf, def->startmode);
1079 if (def->mtu)
1080 virBufferAsprintf(buf, "<mtu size='%d'/>\n", def->mtu);
1081 virInterfaceProtocolDefFormat(buf, def);
1082 }
1083
1084 if (def->type != VIR_INTERFACE_TYPE_BRIDGE)
1085 virInterfaceLinkFormat(buf, &def->lnk);
1086 switch (def->type) {
1087 case VIR_INTERFACE_TYPE_ETHERNET:
1088 if (def->mac)
1089 virBufferAsprintf(buf, "<mac address='%s'/>\n", def->mac);
1090 break;
1091 case VIR_INTERFACE_TYPE_BRIDGE:
1092 virInterfaceBridgeDefFormat(buf, def);
1093 break;
1094 case VIR_INTERFACE_TYPE_BOND:
1095 virInterfaceBondDefFormat(buf, def);
1096 break;
1097 case VIR_INTERFACE_TYPE_VLAN:
1098 virInterfaceVlanDefFormat(buf, def);
1099 break;
1100 }
1101
1102 virBufferAdjustIndent(buf, -2);
1103 virBufferAddLit(buf, "</interface>\n");
1104
1105 return 0;
1106 }
1107
1108
1109 char *
virInterfaceDefFormat(const virInterfaceDef * def)1110 virInterfaceDefFormat(const virInterfaceDef *def)
1111 {
1112 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1113
1114 if (virInterfaceDefDevFormat(&buf, def, VIR_INTERFACE_TYPE_LAST) < 0)
1115 return NULL;
1116
1117 return virBufferContentAndReset(&buf);
1118 }
1119