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