00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define _GNU_SOURCE 1
00024
00025 #include <sys/types.h>
00026 #include <unistd.h>
00027 #include <nic.h>
00028 #include <net/if.h>
00029 #include <net/if_arp.h>
00030 #include <arpa/inet.h>
00031 #include <sys/stat.h>
00032 #include <sys/syslog.h>
00033 #include <malloc.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <stdarg.h>
00037 #include <search.h>
00038 #include <time.h>
00039 #include <errno.h>
00040
00041 #include <libdhcp.h>
00042
00043
00044
00045 #include <netlink/netlink.h>
00046 #include <netlink/netlink-kernel.h>
00047 #include <netlink/rtnetlink-kernel.h>
00048 #include <netlink/msg.h>
00049 #include <netlink/attr.h>
00050 #include <netlink/utils.h>
00051 #include <netlink/addr.h>
00052 #include <netlink/route/rtnl.h>
00053 #include <netlink/route/link.h>
00054 #include <netlink/route/addr.h>
00055 #include <netlink/route/route.h>
00056 extern int nl_get_errno(void);
00057
00058 #define eprint(eh, n, level, arg...) ({ \
00059 if (eh) \
00060 eh(n, level, ## arg); \
00061 })
00062
00063
00064
00065
00066 struct nlh_s
00067 {
00068 struct nl_handle *nl;
00069
00070 void *nic_name_tree;
00071 void *nic_index_tree;
00072 void *nic_foreach_arg;
00073
00074 void *nic_addr_tree;
00075 void *nic_addr_foreach_arg;
00076
00077 void *nic_route_tree;
00078 void *nic_route_foreach_arg;
00079
00080 int ll;
00081 NIC_Error_Handler_t eh;
00082 NIC_VA_Error_Handler_t va_eh;
00083 void *va_eh_arg;
00084 };
00085
00086 NLH_t nic_open(NIC_Error_Handler_t eh)
00087 {
00088 NLH_t nh;
00089
00090 if (!(nh = calloc(1, sizeof(struct nlh_s))))
00091 goto nic_open_fail;
00092
00093 if (!(nh->nl = nl_handle_alloc())) {
00094 eprint(eh, 0, NIC_FATAL, "cannot allocate NIC library handle: %m" );
00095 goto nic_open_fail;
00096 }
00097
00098 if (nl_connect(nh->nl, NETLINK_ROUTE) < 0 ) {
00099 eprint(eh, 0, NIC_FATAL, "cannot connect netlink socket: %m" );
00100 goto nic_open_fail;
00101 }
00102
00103 if (eh) {
00104 nh->ll = NIC_ERR;
00105 nh->eh = eh;
00106 }
00107 return nh;
00108
00109 nic_open_fail:
00110 if (nh) {
00111 if (nh->nl)
00112 nl_handle_destroy(nh->nl);
00113 free(nh);
00114 }
00115 return NULL;
00116 }
00117
00118 static void tdestroy_nil(void *n) {}
00119
00120 void nic_close(struct nlh_s **nhp)
00121 {
00122 struct nlh_s *nh;
00123
00124 if (!nhp || !*nhp)
00125 return;
00126 nh = *nhp;
00127
00128 if (nh->nl) {
00129 nl_close(nh->nl);
00130 nl_handle_destroy(nh->nl);
00131 nh->nl = NULL;
00132 }
00133
00134 if (nh->nic_name_tree) {
00135 tdestroy(nh->nic_name_tree, free);
00136 if (nh->nic_index_tree)
00137 tdestroy(nh->nic_index_tree, tdestroy_nil);
00138 nh->nic_name_tree = 0;
00139 nh->nic_index_tree = 0;
00140 } else if (nh->nic_index_tree) {
00141 tdestroy(nh->nic_index_tree, free);
00142 if (nh->nic_name_tree)
00143 tdestroy(nh->nic_name_tree, tdestroy_nil);
00144 nh->nic_name_tree = 0;
00145 nh->nic_index_tree = 0;
00146 }
00147
00148 if (nh->nic_addr_tree) {
00149 tdestroy(nh->nic_addr_tree, nic_addr_free);
00150 nh->nic_addr_tree = 0;
00151 }
00152
00153 if (nh->nic_route_tree)
00154 {
00155 tdestroy(nh->nic_route_tree, nic_route_free);
00156 nh->nic_route_tree = 0;
00157 }
00158
00159 free(nh);
00160 *nhp = NULL;
00161 }
00162
00163
00164
00165
00166 void nic_sys_logger( NLH_t nh, NIC_Error_Level_t el, char *fmt, ... )
00167 {
00168 if ( (nh == 0L) || ( el > nh->ll ) )
00169 return;
00170 va_list va;
00171
00172 va_start(va, fmt);
00173
00174 if( nh->va_eh )
00175 nh->va_eh ( nh->va_eh_arg, el, fmt, va );
00176 else
00177 vsyslog( el, fmt, va );
00178
00179 va_end(va);
00180
00181 if ( el == LOG_FATAL )
00182 nic_close(&nh);
00183 }
00184
00185 void nic_stderr_logger( NLH_t nh, NIC_Error_Level_t el, char *fmt, ... )
00186 {
00187 if ( (nh == 0L) || ( el > nh->ll ) )
00188 return;
00189
00190 va_list va;
00191
00192 va_start(va, fmt);
00193 if( nh->va_eh )
00194 nh->va_eh ( nh->va_eh_arg, el, fmt, va );
00195 else
00196 {
00197 vfprintf(stderr, fmt, va);
00198 fprintf(stderr,"\n");
00199 fflush(stderr);
00200 }
00201 va_end(va);
00202 }
00203
00204 NIC_Res_t nic_set_loglevel( NLH_t nh, NIC_Error_Level_t ll )
00205 {
00206 if ( nh == 0 )
00207 return NIC_FAIL;
00208
00209 nh -> ll = ll;
00210
00211 return NIC_OK;
00212 }
00213
00214 extern
00215 void nic_set_logger(NLH_t nh, NIC_Error_Handler_t eh)
00216 {
00217 nh -> eh = eh;
00218 }
00219
00220 extern
00221 void nic_set_va_logger(NLH_t nh, NIC_VA_Error_Handler_t va_eh, void *va_eh_arg)
00222 {
00223 nh -> va_eh = va_eh;
00224 nh -> eh = nic_stderr_logger;
00225 }
00226
00227 #ifndef IFQDISCSIZ
00228 #define IFQDISCSIZ 32
00229 #endif
00230
00231 struct nic_s
00232 {
00233 NLH_t nh;
00234
00235 struct nic_link
00236 {
00237 struct nlmsghdr hdr;
00238 struct ifinfomsg ifi;
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 ip_addr_t addr;
00253
00254 ip_addr_t broadcast;
00255
00256 char name[IFNAMSIZ];
00257 char qdisc[IFQDISCSIZ];
00258 uint32_t mtu;
00259 uint32_t link;
00260 uint32_t txqlen;
00261 uint32_t weight;
00262 uint32_t master;
00263 uint32_t cost;
00264 uint32_t priority;
00265 uint32_t protinfo;
00266 struct rtnl_link_stats stats;
00267 struct rtnl_link_ifmap ifmap;
00268
00269 enum nic_mask_e
00270 {
00271 NIC_LINK_ADDRESS = 1,
00272 NIC_LINK_BROADCAST = 2,
00273 NIC_LINK_NAME = 4,
00274 NIC_LINK_MTU = 8,
00275 NIC_LINK_LINK = 16,
00276 NIC_LINK_QDISC = 32,
00277 NIC_LINK_STATS = 64,
00278 NIC_LINK_COST = 128,
00279 NIC_LINK_PRIORITY = 256,
00280 NIC_LINK_MASTER = 512,
00281 NIC_LINK_WIRELESS =1024,
00282 NIC_LINK_PROTINFO =2048,
00283 NIC_LINK_TXQLEN =4096,
00284 NIC_LINK_IFMAP =8192,
00285 NIC_LINK_WEIGHT =16384,
00286 NIC_LINK_OPERSTATE =32768,
00287 NIC_LINK_LINKMODE =65536
00288 } have, change;
00289 } l;
00290 };
00291
00292 static struct nla_policy nic_link_policy[IFLA_MAX+1] = {
00293 [IFLA_IFNAME] = { .type = NLA_STRING,
00294 .maxlen = IFNAMSIZ },
00295 [IFLA_MTU] = { .type = NLA_U32 },
00296 [IFLA_TXQLEN] = { .type = NLA_U32 },
00297 [IFLA_LINK] = { .type = NLA_U32 },
00298 [IFLA_WEIGHT] = { .type = NLA_U32 },
00299 [IFLA_COST] = { .type = NLA_U32 },
00300 [IFLA_PRIORITY] = { .type = NLA_U32 },
00301 [IFLA_PROTINFO] = { .type = NLA_U32 },
00302 [IFLA_MASTER] = { .type = NLA_U32 },
00303 [IFLA_QDISC] = { .type = NLA_STRING,
00304 .maxlen = IFQDISCSIZ },
00305 [IFLA_STATS] = { .minlen = sizeof(struct rtnl_link_stats) },
00306 [IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) },
00307 };
00308
00309 static int nic_name_comparator( const void *p1, const void *p2 )
00310 {
00311 const struct nic_s *n1 = p1, *n2 = p2;
00312 return strcmp(n1->l.name, n2->l.name);
00313 }
00314
00315 static int nic_index_comparator( const void *p1, const void *p2 )
00316 {
00317 const struct nic_s *n1 = p1, *n2 = p2;
00318 return ( (n1->l.ifi.ifi_index == n2->l.ifi.ifi_index)
00319 ? 0
00320 : (n1->l.ifi.ifi_index > n2->l.ifi.ifi_index)
00321 ? 1
00322 : -1
00323 );
00324 }
00325
00326 static int nic_get_links(NLH_t nh, char *if_name, int if_index )
00327 {
00328 struct nic_s snic, *nic = &snic;
00329 memset(&(snic),'\0',sizeof(struct nic_s));
00330 snic.nh = nh;
00331 if( ( if_name ) && (*if_name != '\0') && (if_index != -1) )
00332 strncpy(&(nic->l.name[0]),if_name, IFNAMSIZ);
00333 if( if_index != -1 )
00334 nic->l.ifi.ifi_index = if_index;
00335
00336 nic->l.hdr.nlmsg_type = RTM_GETLINK;
00337
00338 if( (if_name && (*if_name != '\0')) || (if_index != -1))
00339 nic->l.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ATOMIC;
00340 else
00341 nic->l.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
00342
00343 struct nl_msg *msg = nlmsg_build( &(nic->l.hdr) );
00344
00345 if( msg == 0L )
00346 {
00347 if( nh -> eh )
00348 nh -> eh ( nh, NIC_FATAL, "nic_get_links: out of memory" );
00349 return 0;
00350 }
00351
00352 if( nlmsg_append(msg, &(nic->l.ifi), sizeof(struct ifinfomsg), 1) < 0 )
00353 {
00354 if (nh->eh)
00355 nh->eh(nh,NIC_ERR,"nic_get_links: nlmsg_append failed: %d %s\n",
00356 nl_get_errno(), nl_geterror()
00357 );
00358 goto nla_put_failure;
00359 }
00360
00361 if ( (if_name != 0L) && (*if_name != '\0') )
00362 NLA_PUT_STRING(msg, IFLA_IFNAME, if_name);
00363 else
00364 if_name = "";
00365
00366 if ( nl_send_auto_complete( nh->nl, nlmsg_hdr(msg) ) < 0 )
00367 {
00368 if (nh->eh)
00369 nh->eh(nh,NIC_ERR,"nic_get_links: netlink send failed: %d %s\n",
00370 nl_get_errno(), nl_geterror()
00371 );
00372 goto nla_put_failure;
00373 }
00374
00375 struct nic_link *buf = 0;
00376 struct sockaddr_nl kernel;
00377 int rlen;
00378 int nlinks = 0 ;
00379 struct nlmsghdr *hdr = (struct nlmsghdr*)buf;
00380 int remaining = 0;
00381
00382 do
00383 {
00384 if ( (rlen = nl_recv( nh->nl, &kernel, (void*)&buf)) > 0 )
00385 {
00386 if( rlen < (sizeof(struct nlmsghdr) + sizeof(struct ifinfomsg)))
00387 {
00388 nlmsg_free(msg);
00389 return nlinks;
00390 }
00391
00392 hdr = (struct nlmsghdr*)buf;
00393 remaining = rlen;
00394
00395 if( hdr->nlmsg_type != RTM_NEWLINK )
00396 goto return_nlinks;
00397
00398 do
00399 {
00400 memset(&(nic->l), '\0', sizeof(struct nic_link));
00401
00402 memcpy(&(nic->l), hdr, sizeof(struct nlmsghdr));
00403
00404 struct nl_attr *tb[__IFLA_MAX];
00405 int i;
00406 for (i=0; i < __IFLA_MAX; i++) tb[i]=0;
00407
00408 int err =
00409 nlmsg_parse((struct nlmsghdr*)hdr, sizeof(struct ifinfomsg),
00410 (void*)tb, IFLA_MAX, nic_link_policy);
00411
00412 if ( err < 0 )
00413 {
00414 if (nh->eh)
00415 nh->eh(nh,NIC_ERR,"nic_get_links: nl_parse failed: %d %s",
00416 err, nl_geterror()
00417 );
00418 goto return_nlinks;
00419 }
00420
00421 nic->l.ifi =*((struct ifinfomsg*)nlmsg_data((struct nlmsghdr*)hdr));
00422
00423
00424 char *ifn=if_name;
00425 if ( tb[IFLA_IFNAME] )
00426 {
00427 memcpy(&(nic->l.name[0]), nla_data((void*)tb[IFLA_IFNAME]), nla_len((void*)tb[IFLA_IFNAME]));
00428 nic->l.have |= NIC_LINK_NAME;
00429 ifn = &(nic->l.name[0]);
00430 if( nh->eh )
00431 nh->eh(nh,NIC_DEBUG,"nic %s : name: %s", if_name, nic->l.name );
00432 }
00433
00434 if( nh->eh )
00435 nh->eh(nh,NIC_DEBUG,"nic %s: index: %d flags: %x", ifn,
00436 nic->l.ifi.ifi_index, nic->l.ifi.ifi_flags);
00437
00438
00439 if ( tb[IFLA_TXQLEN] )
00440 {
00441 nic->l.txqlen = nla_get_u32((void*)tb[IFLA_TXQLEN]);
00442 nic->l.have |= NIC_LINK_TXQLEN;
00443 if( nh->eh )
00444 nh->eh(nh,NIC_DEBUG,"nic %s txqlen: %d", ifn, nic->l.txqlen);
00445 }
00446
00447 if ( tb[IFLA_MTU] )
00448 {
00449 nic->l.mtu = nla_get_u32((void*)tb[IFLA_MTU]);
00450 nic->l.have |= NIC_LINK_MTU;
00451 if( nh->eh )
00452 nh->eh(nh,NIC_DEBUG,"nic %s mtu: %d", ifn, nic->l.mtu);
00453 }
00454
00455 if ( tb[IFLA_ADDRESS] )
00456 {
00457 nic->l.addr =
00458 ip_addr_binary
00459 ( nla_data((void*)tb[IFLA_ADDRESS]),
00460 nla_len((void*)tb[IFLA_ADDRESS])
00461 );
00462 if( nh->eh )
00463 {
00464 char abuf[32];
00465 nh->eh(nh,NIC_DEBUG,"nic %s addr: %s", ifn,
00466 ip_text_addr(&(nic->l.addr),abuf,32)
00467 );
00468 }
00469 nic->l.have |= NIC_LINK_ADDRESS;
00470 }
00471
00472 if ( tb[IFLA_BROADCAST] )
00473 {
00474 nic->l.broadcast =
00475 ip_addr_binary
00476 ( nla_data((void*)tb[IFLA_BROADCAST]),
00477 nla_len((void*)tb[IFLA_BROADCAST])
00478 );
00479 if( nh->eh )
00480 {
00481 char abuf[32];
00482 nh->eh(nh,NIC_DEBUG,"nic %s broadcast: %s", ifn,
00483 ip_text_addr(&(nic->l.broadcast),abuf,32)
00484 );
00485 }
00486 nic->l.have |= NIC_LINK_BROADCAST;
00487 }
00488
00489 if ( tb[IFLA_LINK] )
00490 {
00491 nic->l.link = nla_get_u32((void*)tb[IFLA_LINK]);
00492 if( nh->eh )
00493 nh->eh(nh,NIC_DEBUG,"nic %s link: %d", ifn, nic->l.link);
00494 nic->l.have |= NIC_LINK_LINK;
00495 }
00496
00497 if ( tb[IFLA_WEIGHT] )
00498 {
00499 nic->l.weight = nla_get_u32((void*)tb[IFLA_WEIGHT]);
00500 if( nh->eh )
00501 nh->eh(nh,NIC_DEBUG,"nic %s weight: %d", ifn, nic->l.weight);
00502 nic->l.have |= NIC_LINK_WEIGHT;
00503 }
00504
00505 if ( tb[IFLA_MASTER] )
00506 {
00507 nic->l.master = nla_get_u32((void*)tb[IFLA_MASTER]);
00508 if( nh->eh )
00509 nh->eh(nh,NIC_DEBUG,"nic %s master: %d", ifn, nic->l.master);
00510 nic->l.have |= NIC_LINK_MASTER;
00511 }
00512
00513 if ( tb[IFLA_COST] )
00514 {
00515 nic->l.cost = nla_get_u32((void*)tb[IFLA_COST]);
00516 if( nh->eh )
00517 nh->eh(nh,NIC_DEBUG,"nic %s cost: %d", ifn, nic->l.cost);
00518 nic->l.have |= NIC_LINK_COST;
00519 }
00520
00521 if ( tb[IFLA_PRIORITY] )
00522 {
00523 nic->l.priority = nla_get_u32((void*)tb[IFLA_PRIORITY]);
00524 if( nh->eh )
00525 nh->eh(nh,NIC_DEBUG,"nic %s priority: %d", ifn, nic->l.priority);
00526 nic->l.have |= NIC_LINK_PRIORITY;
00527 }
00528
00529 if ( tb[IFLA_PROTINFO] )
00530 {
00531 nic->l.priority = nla_get_u32((void*)tb[IFLA_PROTINFO]);
00532 if( nh->eh )
00533 nh->eh(nh,NIC_DEBUG,"nic %s protinfo: %d", ifn, nic->l.protinfo);
00534 nic->l.have |= NIC_LINK_PROTINFO;
00535 }
00536
00537 if ( tb[IFLA_QDISC] )
00538 {
00539 memcpy(&(nic->l.qdisc[0]), nla_data((void*)tb[IFLA_QDISC]), nla_len((void*)tb[IFLA_QDISC]));
00540 nic->l.have |= NIC_LINK_QDISC;
00541 if( nh->eh )
00542 nh->eh(nh,NIC_DEBUG,"nic %s : qdisc: %s", ifn, nic->l.qdisc );
00543 nic->l.have |= NIC_LINK_QDISC;
00544 }
00545
00546 if ( tb[IFLA_STATS] )
00547 {
00548 memcpy
00549 ( &(nic->l.stats),
00550 nla_data((void*)tb[IFLA_STATS]),
00551 sizeof(struct rtnl_link_stats)
00552 );
00553 nic->l.have |= NIC_LINK_STATS;
00554 if( nh->eh )
00555 nh->eh(nh,NIC_DEBUG,"nic %s has stats", ifn);
00556 }
00557
00558 if ( tb[IFLA_MAP] )
00559 {
00560 memcpy
00561 ( &(nic->l.ifmap),
00562 nla_data((void*)tb[IFLA_MAP]),
00563 sizeof(struct rtnl_link_ifmap)
00564 );
00565 nic->l.have |= NIC_LINK_IFMAP;
00566 if( nh->eh )
00567 nh->eh(nh,NIC_DEBUG,"nic %s has map", ifn);
00568 }
00569
00570 nlinks++;
00571 struct nic_s *tnic = 0L, *nnic = 0;
00572
00573 nnic = calloc(1, sizeof(struct nic_s));
00574 if( nnic == 0L )
00575 {
00576 if( nh->eh )
00577 nh->eh (nh, NIC_ERR,"nic_get_links: out of memory");
00578 goto return_nlinks;
00579 }
00580 memcpy(nnic, nic, sizeof(struct nic_s));
00581
00582 if( (nh->nic_name_tree == 0L)
00583 ||((tnic = tfind(nic, &(nh->nic_name_tree), nic_name_comparator)) == 0L)
00584 ) tsearch(nnic, &(nh->nic_name_tree), nic_name_comparator);
00585
00586 if( (nh->nic_index_tree == 0L)
00587 ||((tnic = tfind(nic, &(nh->nic_index_tree), nic_index_comparator)) == 0L)
00588 ) tsearch(nnic, &(nh->nic_index_tree), nic_index_comparator);
00589
00590 if( tnic != 0L )
00591 {
00592
00593 *tnic = *nic ;
00594 free(nnic);
00595 }else
00596 tnic = nnic;
00597
00598 if ( nnic->l.ifi.ifi_index == if_index )
00599
00600 goto return_nlinks;
00601
00602 if ( strcmp(nnic->l.name, if_name) == 0 )
00603
00604 goto return_nlinks;
00605
00606 hdr = nlmsg_next( hdr, &remaining );
00607
00608 } while ( remaining > 0 );
00609 }else
00610 {
00611 if (nh->eh)
00612 nh->eh(nh,NIC_ERR,"nic_get_links: netlink recv failed: %s %d\n",
00613 nl_get_errno(), nl_geterror()
00614 );
00615 goto return_nlinks;
00616 }
00617 }while ( (hdr->nlmsg_type == RTM_NEWLINK) && (remaining > 0) );
00618
00619 return_nlinks:
00620 if( buf )
00621 free(buf);
00622 nlmsg_free(msg);
00623 return nlinks;
00624
00625 nla_put_failure:
00626 nlmsg_free(msg);
00627 return 0;
00628 }
00629
00630 NIC_t nic_by_name(NLH_t nh, char *if_name)
00631 {
00632
00633 struct nic_s snic, *nic=0, **pnic=0;
00634
00635 if( (if_name == 0L) || ( *if_name == '\0' ) )
00636 {
00637 if( nh -> eh )
00638 nh -> eh ( nh, NIC_FATAL, "nic_by_name: invalid nil argument" );
00639 return( 0L );
00640 }
00641
00642 strncpy(&(snic.l.name[0]),if_name, IFNAMSIZ);
00643
00644 if ( (pnic = tfind(&snic, &(nh->nic_name_tree), nic_name_comparator)) != 0L )
00645 return *pnic;
00646
00647 if( ( nic_get_links(nh, if_name, -1) <= 0 )
00648 ||((pnic = tfind(&snic, &(nh->nic_name_tree), nic_name_comparator)) == 0L)
00649 )
00650 {
00651 if( nh -> eh )
00652 nh -> eh ( nh, NIC_ERR, "nic_by_name: no interface named %s found", if_name );
00653 return(0L);
00654 }else
00655 nic = *pnic;
00656
00657 return nic;
00658 }
00659
00660 NIC_t nic_by_index(NLH_t nh, int16_t if_index)
00661 {
00662 struct nic_s snic, *nic=0, **pnic=0;
00663
00664 if( if_index == -1 )
00665 {
00666 if( nh -> eh )
00667 nh -> eh ( nh, NIC_FATAL, "nic_by_index: invalid -1 argument" );
00668 return( 0L );
00669 }
00670
00671 snic.l.ifi.ifi_index = if_index;
00672
00673 if ( (pnic = tfind(&snic, &(nh->nic_index_tree), nic_index_comparator)) != 0L )
00674 return *pnic;
00675
00676
00677 if( ( nic_get_links(nh, "", if_index ) <= 0 )
00678 ||((pnic = tfind(&snic, &(nh->nic_index_tree), nic_index_comparator)) == 0L)
00679 )
00680 {
00681 if( nh -> eh )
00682 nh -> eh ( nh, NIC_ERR, "nic_by_index: no interface with index %d found", if_index );
00683 return(0L);
00684 }else
00685 nic = *pnic;
00686
00687 return nic;
00688 }
00689
00690 struct nic_cbarg
00691 {
00692 NIC_handler_t cb;
00693 void *arg;
00694 };
00695
00696 static void nic_twalker( const void *p, const VISIT which, const int depth )
00697 {
00698 struct nic_s *nic, *const*npp=p;
00699 struct nic_cbarg *cb;
00700
00701 if( (npp == 0L) || ((nic = *npp) == 0L)
00702 ||(nic->nh == 0) || (nic->nh->nic_foreach_arg == 0 )
00703 ||( (which != postorder) && (which != leaf) )
00704 ) return;
00705
00706 cb = nic->nh->nic_foreach_arg;
00707
00708 cb->cb( nic->nh, nic, cb->arg );
00709 }
00710
00711 void nic_foreach(NLH_t nh, NIC_handler_t handler, void *arg)
00712 {
00713 struct nic_cbarg cb = { handler, arg };
00714 struct nic_s snic;
00715
00716 if ( nh->nic_foreach_arg )
00717 return;
00718
00719 nh->nic_foreach_arg = &cb;
00720 memset(&snic, '\0', sizeof(struct nic_s));
00721 snic.l.ifi.ifi_index = -1;
00722 snic.nh = nh;
00723
00724
00725 nic_get_links(nh, "", -1 ) ;
00726
00727 if( nh->nic_name_tree )
00728 twalk( nh->nic_name_tree, nic_twalker);
00729
00730 nh->nic_foreach_arg = 0L;
00731 }
00732
00733 char* nic_get_name( NIC_t nic )
00734 {
00735 if( nic == 0 ) return 0;
00736
00737 return &(nic->l.name[0]);
00738 }
00739
00740 int16_t nic_get_index( NIC_t nic )
00741 {
00742 if ( nic == 0 ) return -1;
00743
00744 return nic->l.ifi.ifi_index ;
00745 }
00746
00747 ip_addr_t nic_get_link_addr(NIC_t nic)
00748 {
00749 ip_addr_t ip;
00750 memset(&ip, '\0', sizeof(ip));
00751 if( nic == 0L )
00752 return ip;
00753 return nic->l.addr;
00754 }
00755
00756 ip_addr_t nic_get_link_broadcast(NIC_t nic)
00757 {
00758 ip_addr_t ip;
00759 memset(&ip, '\0', sizeof(ip));
00760 if( nic == 0L )
00761 return ip;
00762 return nic->l.broadcast;
00763 }
00764
00765 uint32_t nic_get_flags( NIC_t nic )
00766 {
00767 if(nic == 0L)
00768 return 0;
00769 return nic->l.ifi.ifi_flags;
00770 }
00771
00772 NIC_Res_t nic_update( NIC_t nic )
00773 {
00774 if( nic == 0L )
00775 return NIC_FAIL;
00776
00777 memset(&nic->l.hdr, '\0', sizeof(struct nlmsghdr));
00778
00779 nic->l.hdr.nlmsg_type = RTM_SETLINK;
00780 nic->l.hdr.nlmsg_flags = NLM_F_REPLACE | NLM_F_REQUEST | NLM_F_ACK | NLM_F_ROOT | NLM_F_MATCH;
00781 nic->l.hdr.nlmsg_len = sizeof(struct nlmsghdr);
00782
00783 struct nl_msg *msg = nlmsg_build(&(nic->l.hdr));
00784
00785 if ( msg == 0L )
00786 if( nic->nh->eh )
00787 {
00788 nic->nh->eh ( nic->nh, NIC_ERR, "nic_link_update (%s): nlmsg_build failed - %d %s" ,
00789 nic->l.name, nl_get_errno(), nl_geterror()
00790 );
00791 return NIC_FAIL;
00792 }
00793
00794 nlmsg_append( msg, &(nic->l.ifi), sizeof( struct ifinfomsg ), 0);
00795
00796 if( nic->l.have & NIC_LINK_NAME )
00797 NLA_PUT_STRING(msg, IFLA_IFNAME, &(nic->l.name[0]));
00798
00799 if( nic->l.change & NIC_LINK_QDISC )
00800 NLA_PUT_STRING(msg, IFLA_QDISC, &(nic->l.qdisc[0]));
00801
00802 if( nic->l.have & NIC_LINK_LINK )
00803 NLA_PUT_U32(msg, IFLA_LINK, nic->l.link );
00804
00805 if( nic->l.change & NIC_LINK_MTU )
00806 NLA_PUT_U32(msg, IFLA_MTU, nic->l.mtu);
00807
00808 if( nic->l.change & NIC_LINK_TXQLEN )
00809 NLA_PUT_U32(msg, IFLA_TXQLEN, nic->l.txqlen);
00810
00811 if( nic->l.change & NIC_LINK_WEIGHT )
00812 NLA_PUT_U32(msg, IFLA_WEIGHT, nic->l.weight);
00813
00814 if( nic->l.change & NIC_LINK_COST )
00815 NLA_PUT_U32(msg, IFLA_COST, nic->l.cost);
00816
00817 if( nic->l.change & NIC_LINK_PRIORITY )
00818 NLA_PUT_U32(msg, IFLA_PRIORITY, nic->l.priority);
00819
00820 if( nic->l.change & NIC_LINK_PROTINFO )
00821 NLA_PUT_U32(msg, IFLA_PROTINFO, nic->l.protinfo);
00822
00823 if( nl_send_auto_complete(nic->nh->nl, nlmsg_hdr(msg)) < 0 )
00824 {
00825 if (nic->nh->eh)
00826 nic->nh->eh(nic->nh,NIC_ERR,"nic_update_link: send failed - %d %s",
00827 nl_get_errno(), nl_geterror()
00828 );
00829 return NIC_FAIL;
00830 }
00831
00832 nlmsg_free(msg);
00833
00834 if( nl_wait_for_ack(nic->nh->nl) < 0 )
00835 {
00836 if (nic->nh->eh)
00837 nic->nh->eh(nic->nh,NIC_ERR,"nic_update_link failed - %d: %s",
00838 nl_get_errno(), nl_geterror()
00839 );
00840 return NIC_FAIL;
00841 }
00842
00843 return NIC_OK;
00844
00845 nla_put_failure:
00846
00847 if (nic->nh->eh)
00848 nic->nh->eh(nic->nh, NIC_ERR, "nic_update_link append attr failed - out of memory?");
00849
00850 nlmsg_free(msg);
00851
00852 return NIC_FAIL;
00853 }
00854
00855 void nic_set_flags( NIC_t nic, uint32_t flags )
00856 {
00857 if(nic == 0L) return;
00858
00859 nic->l.ifi.ifi_flags = flags;
00860 }
00861
00862 uint32_t nic_get_mtu( NIC_t nic )
00863 {
00864 if((nic == 0L) || ((nic->l.have & NIC_LINK_MTU)==0))
00865 return 0;
00866 return nic->l.mtu;
00867 }
00868
00869 void nic_set_mtu( NIC_t nic, uint32_t mtu )
00870 {
00871 if( nic == 0 ) return ;
00872 nic->l.mtu = mtu;
00873 nic->l.change |= NIC_LINK_MTU;
00874 }
00875
00876 char *nic_get_qdisc( NIC_t nic )
00877 {
00878 if((nic == 0) || ((nic->l.have & NIC_LINK_QDISC)==0))
00879 return 0;
00880 return &(nic->l.qdisc[0]);
00881 }
00882
00883 extern
00884 void nic_set_qdisc( NIC_t nic, char *qdisc )
00885 {
00886 if(nic == 0) return ;
00887 strncpy(&(nic->l.qdisc[0]), qdisc, IFQDISCSIZ);
00888 nic->l.change |= NIC_LINK_QDISC;
00889 }
00890
00891 uint32_t nic_get_txqlen( NIC_t nic )
00892 {
00893 if((nic == 0L) || ((nic->l.have & NIC_LINK_TXQLEN)==0))
00894 return 0;
00895 return nic->l.txqlen;
00896 }
00897
00898 void nic_set_txqlen( NIC_t nic, uint32_t txq )
00899 {
00900 if(nic == 0L) return;
00901 nic->l.txqlen = txq;
00902 nic->l.change |= NIC_LINK_TXQLEN;
00903 }
00904
00905 uint32_t nic_get_link( NIC_t nic )
00906 {
00907 if((nic == 0L) || ((nic->l.have & NIC_LINK_LINK)==0))
00908 return 0;
00909 return nic->l.link;
00910 }
00911
00912 void nic_set_link( NIC_t nic, uint32_t link )
00913 {
00914 if( nic == 0L) return;
00915 nic->l.link = link;
00916 nic->l.change |= NIC_LINK_LINK;
00917 }
00918
00919 uint32_t nic_get_weight( NIC_t nic )
00920 {
00921 if((nic == 0L) || ((nic->l.have & NIC_LINK_WEIGHT)==0))
00922 return 0;
00923 return nic->l.weight;
00924 }
00925
00926 void nic_set_weight( NIC_t nic, uint32_t weight )
00927 {
00928 if( nic == 0L) return;
00929 nic->l.weight = weight;
00930 nic->l.change |= NIC_LINK_WEIGHT;
00931 }
00932
00933 uint32_t nic_get_master( NIC_t nic )
00934 {
00935 if((nic == 0L) || ((nic->l.have & NIC_LINK_MASTER)==0))
00936 return 0;
00937 return nic->l.master;
00938 }
00939
00940 void nic_set_master( NIC_t nic, uint32_t master )
00941 {
00942 if( nic == 0L) return;
00943 nic->l.master = master;
00944 nic->l.change |= NIC_LINK_MASTER;
00945 }
00946
00947 uint32_t nic_get_cost( NIC_t nic )
00948 {
00949 if((nic == 0L) || ((nic->l.have & NIC_LINK_COST)==0))
00950 return 0;
00951 return nic->l.cost;
00952 }
00953
00954 void nic_set_cost( NIC_t nic, uint32_t cost )
00955 {
00956 if( nic == 0L) return;
00957 nic->l.cost = cost;
00958 nic->l.change |= NIC_LINK_COST;
00959 }
00960
00961 uint32_t nic_get_priority( NIC_t nic )
00962 {
00963 if((nic == 0L) || ((nic->l.have & NIC_LINK_PRIORITY)==0))
00964 return 0;
00965 return nic->l.priority;
00966 }
00967
00968 void nic_set_priority( NIC_t nic, uint32_t priority )
00969 {
00970 if( nic == 0L) return;
00971 nic->l.priority = priority;
00972 nic->l.change |= NIC_LINK_PRIORITY;
00973 }
00974
00975 uint32_t nic_get_protinfo( NIC_t nic )
00976 {
00977 if((nic == 0L) || ((nic->l.have & NIC_LINK_PROTINFO)==0))
00978 return 0;
00979 return nic->l.protinfo;
00980 }
00981
00982 void nic_set_protinfo( NIC_t nic, uint32_t protinfo )
00983 {
00984 if( nic == 0L) return;
00985 nic->l.protinfo = protinfo;
00986 nic->l.change |= NIC_LINK_PROTINFO;
00987 }
00988
00989 struct rtnl_link_stats nic_get_stats(NIC_t nic)
00990 {
00991 struct rtnl_link_stats st;
00992 memset(&st, '\0', sizeof(struct rtnl_link_stats));
00993 if((nic == 0L) || ((nic->l.have & NIC_LINK_STATS)==0))
00994 return st;
00995 return nic->l.stats;
00996 }
00997
00998 struct rtnl_link_ifmap nic_get_ifmap(NIC_t nic)
00999 {
01000 struct rtnl_link_ifmap ifm;
01001 memset(&ifm, '\0', sizeof(struct rtnl_link_ifmap));
01002 if((nic == 0L) || ((nic->l.have & NIC_LINK_IFMAP)==0))
01003 return ifm;
01004 return nic->l.ifmap;
01005 }
01006
01007 struct nic_ip_address_s
01008 {
01009 NLH_t nh;
01010
01011
01012 struct nic_addr_s
01013 {
01014 struct nlmsghdr hdr;
01015 struct ifaddrmsg ifa;
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 uint32_t index;
01027 uint32_t flags;
01028 ip_addr_t addr;
01029 ip_addr_t broadcast;
01030 ip_addr_t anycast;
01031 ip_addr_t multicast;
01032 ip_addr_t local;
01033 struct ifa_cacheinfo cacheinfo;
01034 char label [ IFNAMSIZ ];
01035
01036 enum ifa_e
01037 {
01038 NIC_ADDR_ADDRESS = 1,
01039 NIC_ADDR_LOCAL = 2,
01040 NIC_ADDR_LABEL = 4,
01041 NIC_ADDR_BROADCAST = 8,
01042 NIC_ADDR_ANYCAST = 16,
01043 NIC_ADDR_CACHEINFO = 32,
01044 NIC_ADDR_MULTICAST = 64
01045 } have, change;
01046
01047 } nla;
01048 };
01049
01050 static struct nla_policy nic_addr_policy[IFA_MAX+1] = {
01051 [IFA_LABEL] = { .type = NLA_STRING,
01052 .maxlen = IFNAMSIZ },
01053 [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) },
01054 };
01055
01056 static int nic_addr_comparator( const void *p1, const void *p2 )
01057 {
01058 const struct nic_ip_address_s *ipa1=p1, *ipa2=p2;
01059
01060 if( ipa1->nla.ifa.ifa_index > ipa2->nla.ifa.ifa_index )
01061 return 1;
01062 else
01063 if( ipa1->nla.ifa.ifa_index < ipa2->nla.ifa.ifa_index )
01064 return -1;
01065
01066 uint8_t
01067 pfx1 = ipa1->nla.ifa.ifa_prefixlen,
01068 pfx2 = ipa2->nla.ifa.ifa_prefixlen;
01069
01070 const ip_addr_t *ip1=0, *ip2=0;
01071
01072 if( ipa1->nla.have & NIC_ADDR_ADDRESS )
01073 ip1 = &(ipa1->nla.addr);
01074 else
01075 if( ipa1->nla.have & NIC_ADDR_LOCAL )
01076 {
01077 ip1 = &(ipa1->nla.local);
01078 pfx1 = IP_ADDR_SIZE(ip1) * 8;
01079 }
01080
01081 if( ipa2->nla.have & NIC_ADDR_ADDRESS )
01082 ip2 = &(ipa2->nla.addr);
01083 else
01084 if( ipa2->nla.have & NIC_ADDR_LOCAL )
01085 {
01086 ip2 = &(ipa2->nla.local);
01087 pfx2= IP_ADDR_SIZE(ip2) * 8;
01088 }
01089
01090 if( ip1 == 0 )
01091 return -1;
01092
01093 if( ip2 == 0 )
01094 return 1;
01095
01096 uint8_t
01097 alen1 = IP_ADDR_SIZE(ip1),
01098 alen2 = IP_ADDR_SIZE(ip2);
01099
01100 if( alen1 > alen2 )
01101 return 1;
01102 else
01103 if( alen1 < alen2 )
01104 return -1;
01105
01106 if( pfx1 > pfx2 )
01107 return 1;
01108 else
01109 if( pfx1 < pfx2 )
01110 return -1;
01111
01112 const uint8_t
01113 *ap1 = IP_ADDR(ip1),
01114 *ap2 = IP_ADDR(ip2);
01115
01116 for(; alen1 && pfx1; alen1--, pfx1-=8, ap1++, ap2++ )
01117 {
01118 const uint8_t
01119 v1=*ap1,
01120 v2=*ap2;
01121
01122 if( pfx1 < 8 )
01123 {
01124 const uint8_t
01125 vb1 = v1 & ((1 << pfx1)-1),
01126 vb2 = v2 & ((1 << pfx1)-1);
01127 return
01128 ( vb1 > vb2 )
01129 ? 1
01130 : ( vb1 < vb2 )
01131 ? -1
01132 : 0;
01133 }else
01134 {
01135 if( v1 > v2 )
01136 return 1;
01137 if( v1 < v2 )
01138 return -1;
01139 }
01140 }
01141 return 0;
01142 }
01143
01144 static int nic_get_addresses(NLH_t nh, IPaddr_t ipa)
01145 {
01146 struct nic_ip_address_s ipaf, *addr;
01147
01148 if(nh == 0)
01149 return 0;
01150
01151 int n_addrs = 0;
01152 struct nic_addr_s *nla;
01153
01154 if( ipa )
01155 {
01156 ipaf = *ipa;
01157 addr = ipa;
01158 nla = &(ipa->nla);
01159 memset(&(nla->hdr),'\0',sizeof(struct nlmsghdr));
01160 nla->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ATOMIC | NLM_F_MATCH;
01161 }else
01162 {
01163 memset(&ipaf, '\0', sizeof(struct nic_ip_address_s));
01164 ipaf.nh = nh;
01165 addr = &ipaf;
01166 nla = &(ipaf.nla);
01167 addr=&ipaf;
01168 nla->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
01169 }
01170
01171 nla->hdr.nlmsg_type = RTM_GETADDR;
01172
01173 struct nl_msg *msg = nlmsg_build(&(nla->hdr));
01174
01175 if( msg == 0L )
01176 {
01177 if( nh->eh )
01178 nh->eh ( nh, NIC_ERR, "nic_get_addresses: out of memory" );
01179 return n_addrs;
01180 }
01181
01182 if( nlmsg_append(msg, &(nla->ifa), sizeof(struct ifaddrmsg), 0) < 0 )
01183 {
01184 if (nh->eh)
01185 nh->eh(nh,NIC_ERR,"nic_get_addresses: nlmsg_append failed: %d %s\n",
01186 nl_get_errno(), nl_geterror()
01187 );
01188 goto nla_put_failure;
01189 }
01190
01191 if( addr->nla.addr.sa_family )
01192 NLA_PUT(msg, IFLA_ADDRESS,
01193 IP_ADDR_SIZE(&(addr->nla.addr)),
01194 IP_ADDR(&(addr->nla.addr))
01195 );
01196
01197 if ( nl_send_auto_complete( nh->nl, nlmsg_hdr(msg) ) < 0 )
01198 {
01199 if (nh->eh)
01200 nh->eh(nh,NIC_ERR,"nic_get_addresses: send failed: %d %s\n",
01201 nl_get_errno(), nl_geterror()
01202 );
01203 goto nla_put_failure;
01204 }
01205
01206 struct nic_addr_s *buf = 0;
01207
01208 if( buf == 0L )
01209 {
01210 if (nh->eh)
01211 nh->eh(nh,NIC_ERR,"nic_get_addresses: out of memory.");
01212 goto nla_put_failure;
01213 }
01214
01215 struct nlmsghdr *hdr = (struct nlmsghdr *)buf;
01216 struct sockaddr_nl kernel;
01217 int rlen = 0;
01218 int remaining = 0;
01219
01220 do
01221 {
01222 if ( (rlen = nl_recv( nh->nl, &kernel, (void*)&buf)) > 0 )
01223 {
01224 if( rlen < (sizeof(struct nlmsghdr) + sizeof(struct ifaddrmsg)) )
01225 goto nla_return;
01226
01227 hdr = (struct nlmsghdr*)buf;
01228 remaining = rlen;
01229
01230 if( hdr->nlmsg_type != RTM_NEWADDR )
01231 goto nla_return;
01232
01233 do
01234 {
01235 memset(nla, '\0', sizeof(struct nic_addr_s));
01236
01237 memcpy(nla, hdr, sizeof(struct nlmsghdr));
01238
01239 struct nl_attr *tb[__IFA_MAX];
01240
01241 int i;
01242 for (i=0; i < __IFA_MAX; i++) tb[i]=0;
01243 int err =
01244 nlmsg_parse((struct nlmsghdr*)hdr, sizeof(struct ifaddrmsg),
01245 (void*)tb, IFA_MAX, nic_addr_policy);
01246 if( err < 0 )
01247 {
01248 if (nh->eh)
01249 nh->eh(nh,NIC_ERR,"nic_get_addresses: nl_parse failed: %d %s",
01250 err, nl_geterror()
01251 );
01252 goto nla_return;
01253 }
01254
01255 nla->ifa = *((struct ifaddrmsg*)nlmsg_data((struct nlmsghdr*)hdr));
01256
01257 if( tb[ IFA_ADDRESS ] )
01258 {
01259 nla->addr =
01260 ip_addr_binary
01261 ( nla_data((void*)tb[IFA_ADDRESS]),
01262 nla_len((void*)tb[IFA_ADDRESS])
01263 );
01264 if( nh->eh )
01265 {
01266 char abuf[32];
01267 nh->eh(nh, NIC_DEBUG,"nic %d address: %s/%hd",
01268 nla->ifa.ifa_index,
01269 ip_text_addr(&nla->addr, abuf, 32),
01270 nla->ifa.ifa_prefixlen
01271 );
01272 }
01273 nla->have |= NIC_ADDR_ADDRESS;
01274 }
01275
01276 if( tb[ IFA_LOCAL ] )
01277 {
01278 nla->local =
01279 ip_addr_binary
01280 ( nla_data((void*)tb[IFA_ADDRESS]),
01281 nla_len((void*)tb[IFA_ADDRESS])
01282 );
01283 if( nh->eh )
01284 {
01285 char abuf[32];
01286 nh->eh(nh, NIC_DEBUG,"nic %d local (PtP) address: %s",
01287 nla->ifa.ifa_index,
01288 ip_text_addr(&nla->local, abuf, 32)
01289 );
01290 }
01291 nla->have |= NIC_ADDR_LOCAL;
01292 }
01293
01294 if( tb[ IFA_BROADCAST ] )
01295 {
01296 nla->broadcast =
01297 ip_addr_binary
01298 ( nla_data((void*)tb[IFA_BROADCAST]),
01299 nla_len((void*)tb[IFA_BROADCAST])
01300 );
01301 if( nh->eh )
01302 {
01303 char abuf[32];
01304 nh->eh(nh, NIC_DEBUG,"nic %d broadcast address: %s",
01305 nla->ifa.ifa_index,
01306 ip_text_addr(&nla->broadcast, abuf, 32)
01307 );
01308 }
01309 nla->have |= NIC_ADDR_BROADCAST;
01310 }
01311
01312 if( tb[ IFA_ANYCAST ] )
01313 {
01314 nla->anycast =
01315 ip_addr_binary
01316 ( nla_data((void*)tb[IFA_ANYCAST]),
01317 nla_len((void*)tb[IFA_ANYCAST])
01318 );
01319 if( nh->eh )
01320 {
01321 char abuf[32];
01322 nh->eh(nh, NIC_DEBUG,"nic %d anycast address: %s",
01323 nla->ifa.ifa_index,
01324 ip_text_addr(&nla->anycast, abuf, 32)
01325 );
01326 }
01327 nla->have |= NIC_ADDR_ANYCAST;
01328 }
01329
01330 if( tb[ IFA_MULTICAST ] )
01331 {
01332 nla->multicast =
01333 ip_addr_binary
01334 ( nla_data((void*)tb[IFA_MULTICAST]),
01335 nla_len((void*)tb[IFA_MULTICAST])
01336 );
01337 if( nh->eh )
01338 {
01339 char abuf[32];
01340 nh->eh(nh, NIC_DEBUG,"nic %d multicast address: %s",
01341 nla->ifa.ifa_index,
01342 ip_text_addr(&nla->multicast, abuf, 32)
01343 );
01344 }
01345 nla->have |= NIC_ADDR_MULTICAST;
01346 }
01347
01348 if( tb[IFA_CACHEINFO] )
01349 {
01350 memcpy
01351 ( &(nla->cacheinfo),
01352 nla_data((void*)tb[IFA_CACHEINFO]),
01353 sizeof(struct ifa_cacheinfo)
01354 );
01355 if( nh->eh )
01356 nh->eh(nh, NIC_DEBUG,"nic %d have cacheinfo",
01357 nla->ifa.ifa_index
01358 );
01359 nla->have |= NIC_ADDR_CACHEINFO;
01360 }
01361
01362 if( tb[IFA_LABEL] )
01363 {
01364 strncpy
01365 ( &(nla->label[0]),
01366 nla_data((void*)tb[IFA_LABEL]),
01367 nla_len((void*)tb[IFA_LABEL])
01368 );
01369 if( nh->eh )
01370 nh->eh(nh, NIC_DEBUG,"nic %d addr label: %s",
01371 nla->ifa.ifa_index, nla->label
01372 );
01373 nla->have |= NIC_ADDR_LABEL;
01374 }
01375
01376 n_addrs++;
01377
01378 struct nic_ip_address_s **paddr, *taddr=0L, *naddr = 0L;
01379
01380 if( ipa == 0 )
01381 {
01382 naddr = calloc(1, sizeof(struct nic_ip_address_s));
01383 if( naddr == 0L )
01384 {
01385 if( nh->eh )
01386 nh->eh (nh, NIC_ERR, "nic_get_addresses: out of memory.");
01387 goto nla_return;
01388 }
01389 *naddr = *addr;
01390 taddr = addr;
01391 addr = naddr;
01392 naddr = taddr;
01393 taddr = 0;
01394 }
01395
01396 if( (nh->nic_addr_tree == 0L)
01397 ||((paddr = tfind(addr, &(nh->nic_addr_tree), nic_addr_comparator)) == 0L)
01398 ) tsearch(addr, &(nh->nic_addr_tree), nic_addr_comparator);
01399
01400 if( paddr != 0L )
01401 {
01402 taddr = *paddr;
01403 *taddr = *addr;
01404 if( naddr )
01405 free(naddr);
01406 }
01407
01408 if( ipa == 0L )
01409 addr = &ipaf;
01410
01411 if( ipa && ( nic_addr_comparator( ipa , addr ) == 0 ) )
01412 goto nla_return;
01413
01414 hdr = nlmsg_next( hdr, &remaining );
01415
01416 } while ( remaining > 0 );
01417
01418 }else
01419 {
01420 if (nh->eh)
01421 nh->eh(nh,NIC_ERR,"nic_addresses: netlink recv failed: %s %d\n",
01422 nl_get_errno(), nl_geterror()
01423 );
01424 goto nla_return;
01425 }
01426 } while ( (hdr->nlmsg_type == RTM_NEWADDR) && (remaining > 0) );
01427
01428 nla_return:
01429 if( buf )
01430 free(buf);
01431 nlmsg_free(msg);
01432 return n_addrs;
01433
01434 nla_put_failure:
01435 nlmsg_free(msg);
01436 return n_addrs;
01437 }
01438
01439 struct nic_addr_cbarg
01440 {
01441 IPaddr_Handler_t cb;
01442 void *arg;
01443 };
01444
01445 static void nic_addr_twalker( const void *p, const VISIT which, const int depth )
01446 {
01447 struct nic_ip_address_s *addr, *const*app=p;
01448 struct nic_addr_cbarg *cb;
01449
01450 if( (app == 0L) || ((addr = *app) == 0L)
01451 ||(addr->nh == 0) || (addr->nh->nic_addr_foreach_arg == 0 )
01452 ||( (which != postorder) && (which != leaf) )
01453 ) return;
01454
01455 cb = addr->nh->nic_addr_foreach_arg;
01456
01457 cb->cb( addr->nh, addr, cb->arg );
01458 }
01459
01460 void nic_addr_foreach(NLH_t nh, IPaddr_Handler_t handler, void *arg)
01461 {
01462 struct nic_addr_cbarg cb = { handler, arg };
01463
01464 if ( nh->nic_addr_foreach_arg )
01465 return;
01466
01467 nh->nic_addr_foreach_arg = &cb;
01468
01469 nic_get_addresses(nh, 0L);
01470
01471 if( nh->nic_addr_tree )
01472 twalk( nh->nic_addr_tree, nic_addr_twalker);
01473
01474 nh->nic_addr_foreach_arg = 0L;
01475 }
01476
01477 IPaddr_t nic_addr_ip( NLH_t nh, ip_addr_t *ip)
01478 {
01479 if( ( nh == 0L ) || ( ip == 0L )
01480 ||( (ip->sa_family != AF_INET)
01481 &&(ip->sa_family != AF_INET6)
01482 )
01483 ) return 0;
01484
01485 IPaddr_t ipa = calloc(1, sizeof(struct nic_ip_address_s));
01486
01487 if( ipa == 0L )
01488 {
01489 if( nh->eh )
01490 nh->eh(nh, NIC_ERR, "nic_addr_ip: out of memory");
01491 }
01492 ipa->nh = nh;
01493 ipa->nla.addr = *ip;
01494 ipa->nla.have |= NIC_ADDR_ADDRESS;
01495 return ipa;
01496 }
01497
01498 IPaddr_t nic_addr( NLH_t nh, ip_addr_t ip)
01499 {
01500 if( ( nh == 0L )
01501 ||( (ip.sa_family != AF_INET)
01502 &&(ip.sa_family != AF_INET6)
01503 )
01504 ) return 0;
01505
01506 IPaddr_t ipa = calloc(1, sizeof(struct nic_ip_address_s));
01507
01508 if( ipa == 0L )
01509 {
01510 if( nh->eh )
01511 nh->eh(nh, NIC_ERR, "nic_addr_ip: out of memory");
01512 }
01513 ipa->nh = nh;
01514 ipa->nla.addr = ip;
01515 ipa->nla.ifa.ifa_family = ip.sa_family;
01516 ipa->nla.have |= NIC_ADDR_ADDRESS;
01517 return ipa;
01518 }
01519
01520 IPaddr_t nic_addr_local( NLH_t nh, ip_addr_t ip)
01521 {
01522 if( ( nh == 0L )
01523 ||((ip.sa_family != AF_INET)
01524 &&(ip.sa_family != AF_INET6)
01525 )
01526 ) return 0;
01527
01528 IPaddr_t ipa = calloc(1, sizeof(struct nic_ip_address_s));
01529
01530 if( ipa == 0L )
01531 {
01532 if( nh->eh )
01533 nh->eh(nh, NIC_ERR, "nic_addr_ip: out of memory");
01534 }
01535 ipa->nh = nh;
01536 ipa->nla.local = ip;
01537 ipa->nla.have |= NIC_ADDR_LOCAL;
01538 return ipa;
01539 }
01540
01541 ip_addr_t nic_ip_addr( IPaddr_t ipa )
01542 {
01543 ip_addr_t ip;
01544 memset(&ip, '\0', sizeof(ip_addr_t));
01545 if( (ipa == 0L) || ((ipa->nla.have & NIC_ADDR_ADDRESS) == 0))
01546 return ip;
01547 return ipa->nla.addr;
01548 }
01549
01550 ip_addr_t nic_addr_get_local( IPaddr_t ipa )
01551 {
01552 ip_addr_t ip;
01553 memset(&ip, '\0', sizeof(ip_addr_t));
01554 if( (ipa == 0L) || ((ipa->nla.have & NIC_ADDR_LOCAL) == 0))
01555 return ip;
01556 return ipa->nla.local;
01557 }
01558
01559 void nic_addr_set_local( IPaddr_t ipa, ip_addr_t ip )
01560 {
01561 if((ipa == 0L)
01562 ||((ip.sa_family != AF_INET)
01563 &&(ip.sa_family != AF_INET6)
01564 )
01565 ) return;
01566
01567 ipa->nla.local = ip;
01568 ipa->nla.have |= NIC_ADDR_LOCAL;
01569 }
01570
01571 uint8_t nic_addr_get_family( IPaddr_t ipa )
01572 {
01573 if(ipa == 0L) return 0;
01574 return ipa->nla.ifa.ifa_family;
01575 }
01576
01577 uint8_t nic_addr_get_prefix( IPaddr_t ipa)
01578 {
01579 if(ipa == 0L) return 0;
01580 return ipa->nla.ifa.ifa_prefixlen;
01581 }
01582
01583 void nic_addr_set_prefix( IPaddr_t ipa, uint8_t prefix)
01584 {
01585 if( (ipa == 0L)
01586 ||((ipa->nla.ifa.ifa_family == AF_INET) && (prefix > 32))
01587 ||((ipa->nla.ifa.ifa_family == AF_INET6) && (prefix > 128))
01588 )
01589 return;
01590
01591 ipa->nla.ifa.ifa_prefixlen = prefix;
01592 }
01593
01594 ip_addr_t nic_addr_get_broadcast( IPaddr_t ipa )
01595 {
01596 ip_addr_t ip;
01597 memset(&ip, '\0', sizeof(ip_addr_t));
01598 if( (ipa == 0L) || ((ipa->nla.have & NIC_ADDR_BROADCAST) == 0))
01599 return ip;
01600 return ipa->nla.broadcast;
01601 }
01602
01603 void nic_addr_set_broadcast( IPaddr_t ipa, ip_addr_t ip )
01604 {
01605 if( (ipa == 0L)
01606 ||((ip.sa_family != AF_INET)
01607 &&(ip.sa_family != AF_INET6)
01608 )
01609 ) return;
01610
01611 ipa->nla.broadcast = ip;
01612 ipa->nla.have |= NIC_ADDR_BROADCAST;
01613 }
01614
01615 ip_addr_t nic_addr_get_anycast( IPaddr_t ipa )
01616 {
01617 ip_addr_t ip;
01618 memset(&ip, '\0', sizeof(ip_addr_t));
01619 if( (ipa == 0L) || ((ipa->nla.have & NIC_ADDR_ANYCAST) == 0))
01620 return ip;
01621 return ipa->nla.anycast;
01622 }
01623
01624 void nic_addr_set_anycast( IPaddr_t ipa, ip_addr_t ip )
01625 {
01626 if( (ipa == 0L)
01627 ||((ip.sa_family != AF_INET)
01628 &&(ip.sa_family != AF_INET6)
01629 )
01630 ) return;
01631
01632 ipa->nla.anycast = ip;
01633 ipa->nla.have |= NIC_ADDR_ANYCAST;
01634 }
01635
01636 ip_addr_t nic_addr_get_multicast( IPaddr_t ipa )
01637 {
01638 ip_addr_t ip;
01639 memset(&ip, '\0', sizeof(ip_addr_t));
01640 if( (ipa == 0L) || ((ipa->nla.have & NIC_ADDR_MULTICAST) == 0))
01641 return ip;
01642 return ipa->nla.multicast;
01643 }
01644
01645 void nic_addr_set_multicast( IPaddr_t ipa, ip_addr_t ip )
01646 {
01647 if( (ipa == 0L)
01648 ||( (ip.sa_family != AF_INET)
01649 &&(ip.sa_family != AF_INET6)
01650 )
01651 ) return;
01652
01653 ipa->nla.multicast = ip;
01654 ipa->nla.have |= NIC_ADDR_MULTICAST;
01655 }
01656
01657 int8_t nic_addr_get_scope(IPaddr_t ipa)
01658 {
01659 if(ipa == 0L) return 0;
01660
01661 return ipa->nla.ifa.ifa_scope;
01662 }
01663
01664 void nic_addr_set_scope(IPaddr_t ipa, int8_t scope )
01665 {
01666 if(ipa == 0L) return;
01667
01668 ipa->nla.ifa.ifa_scope = scope;
01669 }
01670
01671 uint8_t nic_addr_get_flags(IPaddr_t ipa)
01672 {
01673 if(ipa == 0L) return 0;
01674
01675 return ipa->nla.ifa.ifa_flags;
01676 }
01677
01678 void nic_addr_set_flags(IPaddr_t ipa, uint8_t flags )
01679 {
01680 if(ipa == 0L) return;
01681
01682 ipa->nla.ifa.ifa_flags = flags;
01683 }
01684
01685 const char *nic_addr_get_label(IPaddr_t ipa)
01686 {
01687 if( (ipa == 0L) || ((ipa->nla.have & NIC_ADDR_LABEL) == 0))
01688 return "";
01689 return &(ipa->nla.label[0]);
01690 }
01691
01692 void nic_addr_set_label(IPaddr_t ipa, const char *label)
01693 {
01694 if((ipa == 0L) || (label == 0L)) return;
01695 strncpy(&(ipa->nla.label[0]), label, IFNAMSIZ);
01696 ipa->nla.have |= NIC_ADDR_LABEL;
01697 }
01698
01699 struct ifa_cacheinfo nic_addr_get_cacheinfo( IPaddr_t ipa )
01700 {
01701 struct ifa_cacheinfo ifa_ca;
01702 memset(&ifa_ca, '\0', sizeof(struct ifa_cacheinfo));
01703 if( (ipa == 0L) || ((ipa->nla.have & NIC_ADDR_CACHEINFO) == 0))
01704 return ifa_ca;
01705 return ipa->nla.cacheinfo;
01706 }
01707
01708 void nic_addr_set_cacheinfo( IPaddr_t ipa, struct ifa_cacheinfo *ca)
01709 {
01710 if((ipa == 0L) || (ca == 0L)) return;
01711 ipa->nla.cacheinfo = *ca;
01712 ipa->nla.have |= NIC_ADDR_CACHEINFO;
01713 }
01714
01715 IPaddr_list_t *nic_address_list_new( IPaddr_t ip1, ... )
01716 {
01717 va_list va;
01718 va_start(va, ip1);
01719
01720 IPaddr_list_t *head = calloc(1,sizeof(IPaddr_list_t));
01721 IPaddr_list_node_t *n;
01722 struct nic_ip_address_s *ip;
01723
01724 if( head == 0 )
01725 {
01726 va_end(va);
01727 if( ip1->nh->eh )
01728 ip1->nh->eh ( ip1->nh, NIC_ERR, "out of memory" );
01729 return 0;
01730 }
01731 ip=ip1;
01732 STAILQ_INIT(head);
01733 do
01734 {
01735 n = calloc(1,sizeof(IPaddr_list_node_t));
01736 if ( n == 0L )
01737 {
01738 va_end(va);
01739 free(head);
01740 if( ip->nh->eh )
01741 ip->nh->eh ( ip->nh, NIC_ERR, "out of memory" );
01742 return 0L;
01743 }
01744 n->addr = ip;
01745 STAILQ_INSERT_TAIL( head, n, link );
01746 }while( (ip = va_arg(va, struct nic_ip_address_s*)) != 0) ;
01747 va_end(va);
01748 return(head);
01749 }
01750
01751 void nic_address_list_free( IPaddr_list_t *head )
01752 {
01753 IPaddr_list_node_t *n, *a;
01754
01755 if ( !STAILQ_EMPTY(head) )
01756 {
01757 n = STAILQ_FIRST( head );
01758 do
01759 {
01760 a = STAILQ_NEXT(n, link);
01761 free(n->addr);
01762 free(n);
01763 n = a;
01764 } while (n);
01765 }
01766 }
01767
01768 typedef
01769 enum nic_ar_e
01770 {
01771 NIC_ADD_ADDRESS,
01772 NIC_DELETE_ADDRESS
01773 } NIC_Address_Request;
01774
01775 static
01776 int nic_addr_send( IPaddr_t ipa, NIC_Address_Request req )
01777 {
01778 int err=0;
01779
01780 if(ipa == 0L) return -1;
01781
01782 memset(&(ipa->nla.hdr), '\0', sizeof(struct nlmsghdr));
01783
01784 ipa->nla.hdr.nlmsg_type =
01785 (req == NIC_DELETE_ADDRESS)
01786 ? RTM_DELADDR
01787 : RTM_NEWADDR;
01788
01789 ipa->nla.hdr.nlmsg_flags =
01790 ( (req == NIC_ADD_ADDRESS)
01791 ? (NLM_F_REPLACE | NLM_F_MATCH)
01792 : 0
01793 ) | NLM_F_REQUEST | NLM_F_ACK | NLM_F_ROOT;
01794
01795 ipa->nla.hdr.nlmsg_len = sizeof(struct nlmsghdr);
01796
01797 if( ipa->nla.ifa.ifa_flags == 0 )
01798 ipa->nla.ifa.ifa_flags = IFA_F_PERMANENT;
01799
01800 struct nl_msg *msg = nlmsg_build(&(ipa->nla.hdr));
01801
01802 if ( msg == 0L )
01803 if( ipa->nh->eh )
01804 {
01805 ipa->nh->eh ( ipa->nh, NIC_ERR, "nic_addr_send: nlmsg_build failed - %d %s" ,
01806 nl_get_errno(), nl_geterror()
01807 );
01808 return NIC_FAIL;
01809 }
01810
01811 nlmsg_append( msg, &(ipa->nla.ifa), sizeof( struct ifaddrmsg ), 1);
01812
01813 if( ipa->nla.have & NIC_ADDR_ADDRESS )
01814 {
01815 NLA_PUT(msg, IFA_ADDRESS, IP_ADDR_SIZE(&(ipa->nla.addr)), IP_ADDR( &(ipa->nla.addr) ));
01816 if( (ipa->nla.ifa.ifa_family == AF_INET) && ((ipa->nla.have & NIC_ADDR_LOCAL)==0) )
01817 {
01818 ipa->nla.have |= NIC_ADDR_LOCAL;
01819 ipa->nla.local = ipa->nla.addr;
01820 }
01821 if( ipa->nh->eh && (ipa->nh->ll >= NIC_DEBUG) )
01822 {
01823 char abuf[64];
01824 ipa->nh->eh ( ipa->nh, NIC_DEBUG,"nic_addr_send: add IFA_ADDRESS: %d %s/%d\n",
01825 ipa->nla.ifa.ifa_index,
01826 ip_text_addr(&(ipa->nla.addr),abuf,64),
01827 ipa->nla.ifa.ifa_prefixlen
01828 );
01829 }
01830 }
01831
01832 if( ipa->nla.have & NIC_ADDR_LOCAL )
01833 {
01834 NLA_PUT(msg, IFA_LOCAL, IP_ADDR_SIZE(&(ipa->nla.local)), IP_ADDR( &(ipa->nla.local) ));
01835 if( ipa->nh->eh && (ipa->nh->ll >= NIC_DEBUG) )
01836 {
01837 char abuf[64];
01838 ipa->nh->eh ( ipa->nh, NIC_DEBUG,"nic_addr_send: add IFA_LOCAL: %d %s\n",
01839 ipa->nla.ifa.ifa_index,
01840 ip_text_addr(&(ipa->nla.local),abuf,64)
01841 );
01842 }
01843 }
01844
01845 if( ipa->nla.have & NIC_ADDR_LABEL )
01846 NLA_PUT_STRING(msg, IFA_LABEL, &(ipa->nla.label[0]));
01847
01848 if( ipa->nla.have & NIC_ADDR_BROADCAST )
01849 {
01850 NLA_PUT(msg, IFA_BROADCAST, IP_ADDR_SIZE(&(ipa->nla.broadcast)), IP_ADDR( &(ipa->nla.broadcast) ));
01851 if( ipa->nh->eh )
01852 {
01853 char abuf[64];
01854 ipa->nh->eh ( ipa->nh, NIC_DEBUG,"nic_addr_send: add address: %d broadcast: %s\n",
01855 ipa->nla.ifa.ifa_index,
01856 ip_text_addr(&(ipa->nla.broadcast), abuf, 64)
01857 );
01858 }
01859 }
01860
01861 if( ipa->nla.have & NIC_ADDR_ANYCAST )
01862 NLA_PUT(msg, IFA_ANYCAST, IP_ADDR_SIZE(&(ipa->nla.broadcast)), IP_ADDR( &(ipa->nla.broadcast) ));
01863
01864 if( ipa->nla.have & NIC_ADDR_MULTICAST )
01865 NLA_PUT(msg, IFA_MULTICAST, IP_ADDR_SIZE(&(ipa->nla.broadcast)), IP_ADDR( &(ipa->nla.multicast) ));
01866
01867 if( ipa->nla.have & NIC_ADDR_CACHEINFO )
01868 NLA_PUT(msg, IFA_CACHEINFO, sizeof(struct ifa_cacheinfo), &(ipa->nla.cacheinfo));
01869
01870 if( (err = nl_send_auto_complete(ipa->nh->nl, nlmsg_hdr(msg))) < 0 )
01871 {
01872 if (ipa->nh->eh)
01873 ipa->nh->eh(ipa->nh,NIC_ERR,"nic_addr_send: send failed - %d %d %s",
01874 err, nl_get_errno(), nl_geterror()
01875 );
01876 return NIC_FAIL;
01877 }
01878
01879 nlmsg_free(msg);
01880
01881 int n_tries = 0;
01882 try_again:
01883
01884 if( (n_tries < 10) && ((err= nl_wait_for_ack(ipa->nh->nl)) < 0) )
01885 {
01886 if( err == - EBUSY )
01887 {
01888 struct timespec ts = { 0, 500000000 };
01889 ++n_tries;
01890
01891 nanosleep(&ts,0);
01892 goto try_again;
01893 }
01894
01895 if( err == -EEXIST )
01896 {
01897
01898 return NIC_OK;
01899 }
01900 if (ipa->nh->eh)
01901 ipa->nh->eh(ipa->nh,NIC_ERR,"nic_addr_send failed - %d: %s",
01902 nl_get_errno(), nl_geterror()
01903 );
01904 return NIC_FAIL;
01905 }
01906
01907 return NIC_OK;
01908
01909 nla_put_failure:
01910
01911 if (ipa->nh->eh)
01912 ipa->nh->eh(ipa->nh, NIC_ERR, "nic_addr_send append attr failed - out of memory?");
01913
01914 nlmsg_free(msg);
01915
01916 return NIC_FAIL;
01917 }
01918
01919 NIC_Res_t nic_add_address( NIC_t nic, IPaddr_t ipa)
01920 {
01921 if( ( ipa == 0L ) || (nic == 0L) )
01922 return NIC_FAIL;
01923 ipa->nla.ifa.ifa_index = nic->l.ifi.ifi_index;
01924 return nic_addr_send( ipa, NIC_ADD_ADDRESS );
01925 }
01926
01927 NIC_Res_t nic_remove_address( NIC_t nic, IPaddr_t ipa)
01928 {
01929 if( ( ipa == 0L ) || (nic == 0L) )
01930 return NIC_FAIL;
01931 ipa->nla.ifa.ifa_index = nic->l.ifi.ifi_index;
01932 return nic_addr_send( ipa, NIC_ADD_ADDRESS );
01933 }
01934
01935 NIC_Res_t nic_add_addresses( NIC_t nic, IPaddr_list_t *head )
01936 {
01937 IPaddr_list_node_t *n;
01938 NIC_Res_t r;
01939
01940 STAILQ_FOREACH(n,head,link)
01941 {
01942 if((r = nic_add_address(nic, n->addr)) == NIC_FAIL)
01943 return r;
01944 }
01945 return NIC_OK;
01946 }
01947
01948 NIC_Res_t nic_remove_addresses( NIC_t nic, IPaddr_list_t *head )
01949 {
01950 IPaddr_list_node_t *n;
01951 NIC_Res_t r;
01952
01953 STAILQ_FOREACH(n,head,link)
01954 {
01955 if((r = nic_remove_address(nic, n->addr)) == NIC_FAIL)
01956 return r;
01957 }
01958 return NIC_OK;
01959 }
01960
01961 void nic_addr_free(void *ipa)
01962 {
01963 if (ipa)
01964 free(ipa);
01965 }
01966
01967 struct nic_route_s
01968 {
01969 NLH_t nh;
01970
01971 struct nic_rt_s
01972 {
01973 struct nlmsghdr hdr;
01974 struct rtmsg rtm;
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991 ip_addr_t dst;
01992 ip_addr_t gw;
01993 ip_addr_t src;
01994 ip_addr_t prefsrc;
01995 int32_t oif;
01996 uint32_t priority;
01997 uint32_t protoinfo;
01998 uint32_t flow;
01999 uint32_t session;
02000 uint32_t mp_algo;
02001 struct rta_cacheinfo cacheinfo;
02002 char iif [ IFNAMSIZ ];
02003 uint32_t metrics[ __RTAX_MAX ];
02004
02005 struct nic_rtnh_s
02006 {
02007 struct rtnexthop rtnh;
02008 ip_addr_t gw;
02009 } *hops;
02010 uint32_t n_hops;
02011
02012 enum rt_a_e
02013 {
02014 NIC_RT_DST = 1,
02015 NIC_RT_SRC = 2,
02016 NIC_RT_IIF = 8,
02017 NIC_RT_OIF = 16,
02018 NIC_RT_GATEWAY = 32,
02019 NIC_RT_PRIORITY = 64,
02020 NIC_RT_PREFSRC = 128,
02021 NIC_RT_METRICS = 256,
02022 NIC_RT_MULTIPATH= 512,
02023 NIC_RT_PROTOINFO=1024,
02024 NIC_RT_FLOW =2048,
02025 NIC_RT_CACHEINFO=4096,
02026 NIC_RT_SESSION =8192,
02027 NIC_RT_MP_ALGO= 16384
02028 } have, change;
02029
02030 enum rtax_e
02031 {
02032 NIC_RTAX_LOCK = (1<<RTAX_LOCK),
02033 NIC_RTAX_MTU = (1<<RTAX_MTU),
02034 NIC_RTAX_WINDOW = (1<<RTAX_WINDOW),
02035 NIC_RTAX_RTT = (1<<RTAX_RTT),
02036 NIC_RTAX_RTTVAR = (1<<RTAX_RTTVAR),
02037 NIC_RTAX_SSTHRESH = (1<<RTAX_SSTHRESH),
02038 NIC_RTAX_CWND = (1<<RTAX_CWND),
02039 NIC_RTAX_ADVMSS = (1<<RTAX_ADVMSS),
02040 NIC_RTAX_REORDERING=(1<<RTAX_REORDERING),
02041 NIC_RTAX_HOPLIMIT =(1<<RTAX_HOPLIMIT),
02042 NIC_RTAX_INITCWND =(1<<RTAX_INITCWND),
02043 NIC_RTAX_FEATURES =(1<<RTAX_FEATURES)
02044 } have_metrics, change_metrics;
02045 } rt;
02046 };
02047
02048 typedef struct nic_route_s RT_t;
02049
02050 static struct nla_policy nic_route_policy[RTA_MAX+1] = {
02051 [RTA_IIF] = { .type = NLA_STRING,
02052 .maxlen = IFNAMSIZ, },
02053 [RTA_OIF] = { .type = NLA_U32 },
02054 [RTA_PRIORITY] = { .type = NLA_U32 },
02055 [RTA_FLOW] = { .type = NLA_U32 },
02056 [RTA_MP_ALGO] = { .type = NLA_U32 },
02057 [RTA_CACHEINFO] = { .minlen = sizeof(struct rta_cacheinfo) },
02058 [RTA_METRICS] = { .type = NLA_NESTED },
02059 [RTA_MULTIPATH] = { .type = NLA_NESTED },
02060 };
02061
02062 static int nic_route_comparator( const void *p1, const void *p2 )
02063 {
02064 const RT_t *rt1 = p1, *rt2 = p2;
02065
02066 if( rt1->rt.rtm.rtm_table != rt2->rt.rtm.rtm_table )
02067 return
02068 ( (rt1->rt.rtm.rtm_table > rt2->rt.rtm.rtm_table )
02069 ? 1
02070 : -1
02071 );
02072
02073 if ( rt1->rt.rtm.rtm_family != rt2->rt.rtm.rtm_family )
02074 return
02075 ( ( rt1->rt.rtm.rtm_family > rt2->rt.rtm.rtm_family )
02076 ? 1
02077 : -1
02078 );
02079
02080 if ( rt1->rt.rtm.rtm_type != rt2->rt.rtm.rtm_type )
02081 return
02082 ( ( rt1->rt.rtm.rtm_type > rt2->rt.rtm.rtm_type )
02083 ? 1
02084 : -1
02085 );
02086
02087 if ( rt1->rt.rtm.rtm_scope != rt2->rt.rtm.rtm_scope )
02088 return
02089 ( ( rt1->rt.rtm.rtm_scope > rt2->rt.rtm.rtm_scope )
02090 ? 1
02091 : -1
02092 );
02093
02094 if ( rt1->rt.rtm.rtm_protocol != rt2->rt.rtm.rtm_protocol )
02095 return
02096 ( ( rt1->rt.rtm.rtm_protocol > rt2->rt.rtm.rtm_protocol )
02097 ? 1
02098 : -1
02099 );
02100
02101 if( rt1->rt.have & NIC_RT_OIF )
02102 {
02103 if( ( rt2->rt.have & NIC_RT_OIF ) == 0 )
02104 return 1;
02105 else
02106 {
02107 if( rt1->rt.oif != rt2->rt.oif )
02108 return
02109 ( (rt1->rt.oif > rt2->rt.oif)
02110 ? 1
02111 : -1
02112 );
02113 }
02114 }else
02115 if( rt2->rt.have & NIC_RT_OIF )
02116 return -1;
02117
02118 if( rt1->rt.have & NIC_RT_IIF )
02119 {
02120 if( ( rt2->rt.have & NIC_RT_IIF ) == 0 )
02121 return 1;
02122 else
02123 {
02124 int c = strcmp(&(rt1->rt.iif[0]),&(rt2->rt.iif[0]));
02125 if( c != 0 )
02126 return c;
02127 }
02128 }else
02129 if( rt2->rt.have & NIC_RT_OIF )
02130 return -1;
02131
02132 if( rt1->rt.have & NIC_RT_DST )
02133 {
02134 if( (rt2->rt.have & NIC_RT_DST) == 0 )
02135 return 1;
02136 else
02137 {
02138
02139 if( rt1->rt.dst.sa_family != rt2->rt.dst.sa_family )
02140 return
02141 ( ( rt1->rt.dst.sa_family > rt2->rt.dst.sa_family )
02142 ? 1
02143 : -1
02144 );
02145
02146 if( rt1->rt.rtm.rtm_dst_len != rt2->rt.rtm.rtm_dst_len )
02147 return
02148 ( ( rt1->rt.rtm.rtm_dst_len > rt2->rt.rtm.rtm_dst_len )
02149 ? 1
02150 : -1
02151 );
02152
02153 uint8_t
02154 *ap1 = IP_ADDR( &(rt1->rt.dst) ),
02155 *ap2 = IP_ADDR( &(rt2->rt.dst) ),
02156 pfx1 = rt1->rt.rtm.rtm_dst_len;
02157
02158 if( pfx1 == 0 )
02159 pfx1 = IP_ADDR_SIZE( &(rt1->rt.dst) );
02160
02161 int cr = memcmp( ap1, ap2,
02162 pfx1 / 8
02163 );
02164 if ( cr != 0 )
02165 return cr;
02166 uint8_t
02167 v1 = ((uint8_t*)IP_ADDR( &(rt1->rt.dst) ))[ pfx1 / 8 ]
02168 & ( ( 1 << ( pfx1 % 8 ) ) - 1),
02169 v2 = ((uint8_t*)IP_ADDR( &(rt2->rt.dst) ))[ pfx1 / 8 ]
02170 & ( ( 1 << ( pfx1 % 8 ) ) - 1);
02171
02172 if( v1 != v2 )
02173 return
02174 (
02175 (v1 > v2)
02176 ? 1
02177 : -1
02178 );
02179
02180 if( rt1->rt.have & NIC_RT_PRIORITY )
02181 {
02182 if( (rt2->rt.have & NIC_RT_PRIORITY) == 0 )
02183 return -1;
02184
02185 if( rt1->rt.priority != rt2->rt.priority )
02186 return
02187 ( (rt1->rt.priority > rt2->rt.priority)
02188 ? -1
02189 : 1
02190 );
02191 }
02192 }
02193 }else
02194 if( rt2->rt.have & NIC_RT_DST )
02195 return -1;
02196
02197 if( rt1->rt.have & NIC_RT_SRC )
02198 {
02199 if( (rt2->rt.have & NIC_RT_SRC) == 0 )
02200 return 1;
02201 else
02202 {
02203 if( rt1->rt.src.sa_family != rt2->rt.src.sa_family )
02204 return
02205 ( ( rt1->rt.src.sa_family > rt2->rt.src.sa_family )
02206 ? 1
02207 : -1
02208 );
02209
02210 if( rt1->rt.rtm.rtm_src_len != rt2->rt.rtm.rtm_src_len )
02211 return
02212 ( ( rt1->rt.rtm.rtm_src_len > rt2->rt.rtm.rtm_src_len )
02213 ? 1
02214 : -1
02215 );
02216
02217 uint8_t
02218 *ap1 = IP_ADDR( &(rt1->rt.src) ),
02219 *ap2 = IP_ADDR( &(rt2->rt.src) ),
02220 pfx1 = rt1->rt.rtm.rtm_src_len;
02221
02222 if( pfx1 == 0 )
02223 pfx1 = IP_ADDR_SIZE( &(rt1->rt.src) );
02224
02225 int cr = memcmp( ap1, ap2,
02226 rt1->rt.rtm.rtm_src_len / 8
02227 );
02228 if ( cr != 0 )
02229 return cr;
02230 uint8_t
02231 v1 = ((uint8_t*)IP_ADDR( &(rt1->rt.src) ))[ pfx1 / 8 ]
02232 & ( ( 1 << ( rt1->rt.rtm.rtm_src_len % 8 ) ) - 1),
02233 v2 = ((uint8_t*)IP_ADDR( &(rt2->rt.src) ))[ pfx1 / 8 ]
02234 & ( ( 1 << ( pfx1 % 8 ) ) - 1);
02235
02236 if( v1 != v2 )
02237 return
02238 (
02239 (v1 > v2)
02240 ? 1
02241 : -1
02242 );
02243
02244 if( rt1->rt.have & NIC_RT_PRIORITY )
02245 {
02246 if( (rt2->rt.have & NIC_RT_PRIORITY) == 0 )
02247 return -1;
02248
02249 if( rt1->rt.priority != rt2->rt.priority )
02250 return
02251 ( (rt1->rt.priority > rt2->rt.priority)
02252 ? 1
02253 : -1
02254 );
02255 }
02256 }
02257 }else
02258 if (rt2->rt.have & NIC_RT_SRC)
02259 return -1;
02260
02261 if ( rt1->rt.have & NIC_RT_GATEWAY )
02262 {
02263 if((rt2->rt.have & NIC_RT_GATEWAY)==0)
02264 return 1;
02265 {
02266
02267 if( rt1->rt.gw.sa_family != rt2->rt.gw.sa_family )
02268 return
02269 ( ( rt1->rt.gw.sa_family > rt2->rt.gw.sa_family )
02270 ? 1
02271 : -1
02272 );
02273
02274 uint8_t
02275 *ap1 = IP_ADDR( &(rt1->rt.gw) ),
02276 *ap2 = IP_ADDR( &(rt2->rt.gw) );
02277
02278 int cr = memcmp( ap1, ap2,
02279 IP_ADDR_SIZE(&(rt1->rt.gw))
02280 );
02281
02282 if( cr != 0 )
02283 return cr;
02284 }
02285 }else
02286 if (rt2->rt.have & NIC_RT_GATEWAY)
02287 return -1;
02288
02289 if ( rt1->rt.have & NIC_RT_PREFSRC )
02290 {
02291 if((rt2->rt.have & NIC_RT_PREFSRC)==0)
02292 return 1;
02293 {
02294
02295 if( rt1->rt.prefsrc.sa_family != rt2->rt.prefsrc.sa_family )
02296 return
02297 ( ( rt1->rt.prefsrc.sa_family > rt2->rt.prefsrc.sa_family )
02298 ? 1
02299 : -1
02300 );
02301
02302 uint8_t
02303 *ap1 = IP_ADDR( &(rt1->rt.prefsrc) ),
02304 *ap2 = IP_ADDR( &(rt2->rt.prefsrc) );
02305
02306 int cr = memcmp( ap1, ap2,
02307 IP_ADDR_SIZE(&(rt1->rt.prefsrc))
02308 );
02309
02310 if( cr != 0 )
02311 return cr;
02312 }
02313 } else
02314 if (rt2->rt.have & NIC_RT_PREFSRC)
02315 return -1;
02316 return 0;
02317 }
02318
02319 static int nic_get_routes(NLH_t nh, RT_t *rt)
02320 {
02321 RT_t srt, *rtp=0;
02322 struct nic_rt_s *rta=0;
02323 int n_routes = 0;
02324
02325 if(nh == 0)
02326 return 0;
02327
02328 if( rt )
02329 {
02330 srt = *rt;
02331 rtp = rt;
02332 rta = &(rt->rt);
02333 memset(&(rta->hdr),'\0',sizeof(struct nlmsghdr));
02334 rta->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ATOMIC | NLM_F_MATCH;
02335 }else
02336 {
02337 memset(&srt, '\0', sizeof(RT_t));
02338 srt.nh = nh;
02339 rtp = &srt;
02340 rta = &(rtp->rt);
02341 rta->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
02342 }
02343
02344 rta->hdr.nlmsg_type = RTM_GETROUTE;
02345
02346 struct nl_msg *msg = nlmsg_build(&(rta->hdr));
02347
02348 if( msg == 0L )
02349 {
02350 if( nh->eh )
02351 nh->eh ( nh, NIC_ERR, "nic_get_routes: out of memory" );
02352 return n_routes;
02353 }
02354
02355 if( nlmsg_append(msg, &(rta->rtm), sizeof(struct rtmsg), 0) < 0 )
02356 {
02357 if (nh->eh)
02358 nh->eh(nh,NIC_ERR,"nic_get_routes: nlmsg_append failed: %d %s\n",
02359 nl_get_errno(), nl_geterror()
02360 );
02361 goto nla_put_failure;
02362 }
02363
02364 if( rta->rtm.rtm_dst_len && rta->dst.sa_family
02365 &&(rta->have & NIC_RT_DST)
02366 )
02367 NLA_PUT(msg, RTA_DST,
02368 IP_ADDR_SIZE(&(rta->dst)),
02369 IP_ADDR(&(rta->dst))
02370 );
02371
02372 if( (rta->have & NIC_RT_OIF) && (rta->oif > -1) )
02373 NLA_PUT_U32(msg, RTA_OIF, rta->oif);
02374
02375 if( rta->gw.sa_family
02376 &&(rta->have & NIC_RT_GATEWAY)
02377 )
02378 NLA_PUT(msg, RTA_GATEWAY,
02379 IP_ADDR_SIZE(&(rta->gw)),
02380 IP_ADDR(&(rta->gw))
02381 );
02382
02383 if( rta->rtm.rtm_src_len && rta->src.sa_family
02384 &&(rta->have & NIC_RT_SRC)
02385 )
02386 NLA_PUT(msg, RTA_SRC,
02387 IP_ADDR_SIZE(&(rta->src)),
02388 IP_ADDR(&(rta->src))
02389 );
02390
02391 if( (rta->have & NIC_RT_IIF) && (rta->iif[0] != '\0') )
02392 NLA_PUT_STRING(msg, RTA_IIF, &(rta->iif[0]));
02393
02394 if ( nl_send_auto_complete( nh->nl, nlmsg_hdr(msg) ) < 0 )
02395 {
02396 if (nh->eh)
02397 nh->eh(nh,NIC_ERR,"nic_get_routes: send failed: %d %s\n",
02398 nl_get_errno(), nl_geterror()
02399 );
02400 goto nla_put_failure;
02401 }
02402
02403 struct RT_t *buf =0;
02404 struct nlmsghdr *hdr = (struct nlmsghdr *)buf;
02405 struct sockaddr_nl kernel;
02406 int rlen = 0;
02407 int remaining = 0;
02408
02409 do
02410 {
02411 if ( (rlen = nl_recv( nh->nl, &kernel, (void*)&buf)) > 0 )
02412 {
02413 if( rlen < (sizeof(struct nlmsghdr) + sizeof(struct rtmsg)) )
02414 goto rta_return;
02415
02416 hdr = (struct nlmsghdr*)buf;
02417 remaining = rlen;
02418
02419 if( hdr->nlmsg_type != RTM_NEWROUTE )
02420 goto rta_return;
02421
02422 do
02423 {
02424 memset(rta, '\0', sizeof(struct nic_rt_s));
02425
02426 memcpy(rta, hdr, sizeof(struct nlmsghdr));
02427
02428 struct nl_attr *tb[__RTA_MAX];
02429 int i;
02430 for (i=0; i < __RTA_MAX; i++) tb[i]=0;
02431
02432 int err =
02433 nlmsg_parse((struct nlmsghdr*)hdr, sizeof(struct rtmsg),
02434 (void*)tb, RTA_MAX, nic_route_policy);
02435 if ( err < 0 )
02436 {
02437 if (nh->eh)
02438 nh->eh(nh,NIC_ERR,"nic_get_routes: nl_parse failed: %d %s",
02439 err, nl_geterror()
02440 );
02441 goto rta_return;
02442 }
02443
02444 rta->rtm = *((struct rtmsg*)nlmsg_data((struct nlmsghdr*)hdr));
02445
02446 if( ( nh->eh ) && (nh->ll >= NIC_DEBUG))
02447 {
02448 nh->eh(nh, NIC_DEBUG,"\ntable: %d\ndst_len: %d\nsrc_len: %d\nscope: %d\ntype: %d\nprotocol: %d",
02449 rta->rtm.rtm_table, rta->rtm.rtm_dst_len, rta->rtm.rtm_src_len,
02450 rta->rtm.rtm_scope, rta->rtm.rtm_type, rta->rtm.rtm_protocol
02451 );
02452 }
02453
02454 if ( tb[RTA_DST] )
02455 {
02456 rta->dst =
02457 ip_addr_binary
02458 ( nla_data((void*)tb[RTA_DST]),
02459 nla_len((void*)tb[RTA_DST])
02460 );
02461 rta->have |= NIC_RT_DST;
02462 if( nh->eh )
02463 {
02464 char abuf[64];
02465 nh->eh (nh, NIC_DEBUG, "nic route: dst: %s/%d",
02466 ip_text_addr(&(rta->dst),abuf,64),
02467 rta->rtm.rtm_dst_len
02468 );
02469 }
02470 }
02471
02472 if ( tb[RTA_OIF] )
02473 {
02474 rta->oif = nla_get_u32( (void*) tb[RTA_OIF] );
02475 rta->have |= NIC_RT_OIF ;
02476 if( nh->eh )
02477 nh->eh (nh, NIC_DEBUG, "nic route: oif: %d", rta->oif);
02478 }
02479
02480 if ( tb[RTA_GATEWAY] )
02481 {
02482 rta->gw =
02483 ip_addr_binary
02484 ( nla_data((void*)tb[RTA_GATEWAY]),
02485 nla_len((void*)tb[RTA_GATEWAY])
02486 );
02487 rta->have |= NIC_RT_GATEWAY;
02488 if( nh->eh )
02489 {
02490 char abuf[64];
02491 nh->eh (nh, NIC_DEBUG, "nic route: gw: %s",
02492 ip_text_addr(&(rta->gw),abuf,64)
02493 );
02494 }
02495 }
02496
02497 if ( tb[RTA_SRC] )
02498 {
02499 rta->src =
02500 ip_addr_binary
02501 ( nla_data((void*)tb[RTA_SRC]),
02502 nla_len((void*)tb[RTA_SRC])
02503 );
02504 rta->have |= NIC_RT_SRC;
02505 if( nh->eh )
02506 {
02507 char abuf[64];
02508 nh->eh (nh, NIC_DEBUG, "nic route: src: %s/%d",
02509 ip_text_addr(&(rta->src),abuf,64),
02510 rta->rtm.rtm_src_len
02511 );
02512 }
02513 }
02514
02515 if ( tb[RTA_IIF] )
02516 {
02517 memcpy( &(rta->iif),
02518 nla_data( (void*) tb[RTA_IIF] ),
02519 nla_len((void*) tb[RTA_IIF] )
02520 );
02521 rta->have |= NIC_RT_IIF ;
02522 if( nh->eh )
02523 nh->eh (nh, NIC_DEBUG, "nic route: iif: %s", rta->iif);
02524 }
02525
02526 if ( tb[RTA_PREFSRC] )
02527 {
02528 rta->prefsrc =
02529 ip_addr_binary
02530 ( nla_data((void*)tb[RTA_PREFSRC]),
02531 nla_len((void*)tb[RTA_PREFSRC])
02532 );
02533 rta->have |= NIC_RT_PREFSRC;
02534 if( nh->eh )
02535 {
02536 char abuf[64];
02537 nh->eh (nh, NIC_DEBUG, "nic route: prefsrc: %s",
02538 ip_text_addr(&(rta->prefsrc),abuf,64)
02539 );
02540 }
02541 }
02542
02543 if ( tb[RTA_PRIORITY] )
02544 {
02545 rta->priority = nla_get_u32( (void*)tb[RTA_PRIORITY]);
02546 rta->have |= NIC_RT_PRIORITY;
02547 if( nh->eh )
02548 nh->eh (nh, NIC_DEBUG, "nic route: priority: %d", rta->priority);
02549 }
02550
02551 if ( tb[RTA_PROTOINFO] )
02552 {
02553 rta->protoinfo = nla_get_u32( (void*)tb[RTA_PROTOINFO]);
02554 rta->have |= NIC_RT_PROTOINFO;
02555 if( nh->eh )
02556 nh->eh (nh, NIC_DEBUG, "nic route: protoinfo: %x", rta->protoinfo);
02557 }
02558
02559 if ( tb[RTA_FLOW] )
02560 {
02561 rta->flow = nla_get_u32( (void*)tb[RTA_FLOW]);
02562 rta->have |= NIC_RT_FLOW;
02563 if( nh->eh )
02564 nh->eh (nh, NIC_DEBUG, "nic route: flow: %x", rta->flow);
02565 }
02566
02567 if ( tb[RTA_CACHEINFO] )
02568 {
02569 memcpy( &(rta->cacheinfo),
02570 nla_data((void*)tb[RTA_CACHEINFO]),
02571 sizeof(struct rta_cacheinfo)
02572 );
02573 rta->have |= NIC_RT_CACHEINFO;
02574 if( nh->eh )
02575 nh->eh (nh, NIC_DEBUG, "nic route: have cacheinfo");
02576 }
02577
02578 if ( tb[RTA_SESSION] )
02579 {
02580 rta->session = nla_get_u32( (void*)tb[RTA_SESSION]);
02581 rta->have |= NIC_RT_SESSION;
02582 if( nh->eh )
02583 nh->eh (nh, NIC_DEBUG, "nic route: session: %d", rta->session);
02584 }
02585
02586 if ( tb[RTA_MP_ALGO] )
02587 {
02588 rta->mp_algo = nla_get_u32( (void*)tb[RTA_MP_ALGO]);
02589 rta->have |= NIC_RT_MP_ALGO;
02590 if( nh->eh )
02591 nh->eh (nh, NIC_DEBUG, "nic route: mp algorithm: %x", rta->mp_algo);
02592 }
02593
02594 if ( tb[RTA_METRICS] )
02595 {
02596 struct nlattr *rtax_tb [ __RTAX_MAX ];
02597 int m;
02598 for(m=0; m < __RTAX_MAX; m++) rtax_tb[m] = 0L;
02599
02600 err = nla_parse_nested( rtax_tb, RTAX_MAX, (void*)tb[RTA_METRICS], 0L);
02601 if( err < 0 )
02602 {
02603 if( nh->eh )
02604 nh->eh
02605 (nh, NIC_ERR, "nic route: parse of RTAX metrics failed - %d %s",
02606 nl_get_errno(), nl_geterror()
02607 );
02608
02609 }else
02610 {
02611 for( m = 0; m < __RTAX_MAX ; m++ )
02612 {
02613 if( rtax_tb [ m ] )
02614 {
02615 rta->metrics[ m ] = nla_get_u32( (void*) rtax_tb [ m ] );
02616 rta->have_metrics |= 1<<(m+1);
02617 }
02618 }
02619 }
02620 }
02621
02622 if ( tb[RTA_MULTIPATH] )
02623 {
02624 size_t rtnh_len = nla_len((void*)tb[RTA_MULTIPATH]);
02625
02626 struct rtnexthop
02627 *rtnhs = nla_data((void*)tb[RTA_MULTIPATH]),
02628 *rtnhe = (struct rtnexthop*)(((unsigned long)rtnhs) + rtnh_len),
02629 *rtnh = rtnhs;
02630
02631 while( rtnh < rtnhe )
02632 {
02633 rta->n_hops += 1;
02634 rtnh = RTNH_NEXT(rtnh);
02635 }
02636
02637 rta->hops = calloc(rta->n_hops, sizeof(struct nic_rtnh_s));
02638
02639 if( rta->hops == 0L )
02640 {
02641 if( nh->eh )
02642 nh->eh
02643 (nh, NIC_ERR, "nic route: parse of route next hops failed - out of memory.");
02644
02645 }else
02646 {
02647 struct nic_rtnh_s *nic_rtnh = rta->hops;
02648 for(rtnh = rtnhs; rtnh < rtnhe; rtnh = RTNH_NEXT(rtnh), nic_rtnh++ )
02649 {
02650 nic_rtnh->rtnh = *rtnh;
02651 if( rtnh->rtnh_len > sizeof(struct rtnexthop) )
02652 {
02653 struct nlattr *rtnhtb[ __RTA_MAX ];
02654 nla_parse((void*)rtnhtb, RTA_MAX, (struct nlattr *) RTNH_DATA(rtnh),
02655 rtnh->rtnh_len - sizeof(struct rtnexthop), NULL
02656 );
02657 if ( rtnhtb[RTA_GATEWAY] )
02658 {
02659 nic_rtnh->gw =
02660 ip_addr_binary
02661 ( nla_data( (void*) rtnhtb[RTA_GATEWAY] ),
02662 nla_len ( (void*) rtnhtb[RTA_GATEWAY] )
02663 );
02664 }
02665 }
02666 }
02667 }
02668 }
02669
02670 n_routes++;
02671
02672 RT_t **prt=0, *trt=0L, *frt=rt, *nrt = 0L;
02673
02674 if( rt == 0 )
02675 {
02676 nrt = calloc(1, sizeof(struct nic_route_s));
02677 if( nrt == 0L )
02678 {
02679 if( nh->eh )
02680 nh->eh (nh, NIC_ERR, "nic_get_routes: out of memory.");
02681 goto rta_return;
02682 }
02683 *nrt= *rtp;
02684 nh->eh(nh,NIC_DEBUG," new route %p - rta: %p rtp->nh: %p", nrt, rta, nrt->nh);
02685 trt = rtp;
02686 rtp = nrt;
02687 nrt = trt;
02688 trt = 0;
02689 }
02690
02691 if( (nh->nic_route_tree == 0L)
02692 ||((prt = tfind(rtp, &(nh->nic_route_tree), nic_route_comparator)) == 0L)
02693 )
02694 {
02695 tsearch(rtp, &(nh->nic_route_tree), nic_route_comparator);
02696 nh->eh(nh,NIC_DEBUG," route tsearch %p - nh: %p", rtp, rtp->nh);
02697 }
02698
02699 if( prt != 0L )
02700 {
02701 trt = *prt;
02702 *trt = *rtp;
02703 frt = trt;
02704 nh->eh(nh,NIC_DEBUG," route found %p - freeing %p", trt, rtp);
02705 if( nrt )
02706 free(rtp);
02707 }
02708
02709 if( rt == 0L )
02710 rtp = &srt;
02711 else
02712 if( nic_route_comparator( frt , rtp ) == 0 )
02713 goto rta_return;
02714
02715 hdr = nlmsg_next( hdr, &remaining );
02716
02717 } while ( remaining > 0 );
02718
02719 }else
02720 {
02721 if (nh->eh)
02722 nh->eh(nh,NIC_ERR,"nic_get_routes: netlink recv failed: %s %d\n",
02723 nl_get_errno(), nl_geterror()
02724 );
02725 goto rta_return;
02726 }
02727 } while ( (hdr->nlmsg_type == RTM_NEWROUTE) && (remaining > 0) );
02728
02729 rta_return:
02730 if( buf )
02731 free(buf);
02732 nlmsg_free(msg);
02733 return n_routes;
02734
02735 nla_put_failure:
02736 nlmsg_free(msg);
02737 return n_routes;
02738 }
02739
02740 struct nic_route_cbarg
02741 {
02742 IProute_handler_t cb;
02743 void *arg;
02744 };
02745
02746 static void nic_route_twalker( const void *p, const VISIT which, const int depth )
02747 {
02748 struct nic_route_s *route, *const*app=p;
02749 struct nic_route_cbarg *cb;
02750
02751 if( (app == 0L) || ((route = *app) == 0L)
02752 ||(route->nh == 0) || (route->nh->nic_route_foreach_arg == 0 )
02753 ||( (which != postorder) && (which != leaf) )
02754 ) return;
02755
02756 cb = route->nh->nic_route_foreach_arg;
02757
02758 cb->cb( route->nh, route, cb->arg );
02759 }
02760
02761 void nic_route_foreach(NLH_t nh, IProute_handler_t handler, void *arg)
02762 {
02763 struct nic_route_cbarg cb = { handler, arg };
02764
02765 if ( nh->nic_route_foreach_arg )
02766 return;
02767
02768 nh->nic_route_foreach_arg = &cb;
02769
02770 nic_get_routes(nh, 0L);
02771
02772 if( nh->nic_route_tree )
02773 twalk( nh->nic_route_tree, nic_route_twalker);
02774
02775 nh->nic_route_foreach_arg = 0L;
02776 }
02777
02778 int32_t nic_route_get_table(IProute_t rt)
02779 {
02780 if( rt == 0L ) return 0;
02781 return rt->rt.rtm.rtm_table;
02782 }
02783
02784 void nic_route_set_table(IProute_t rt, uint8_t table)
02785 {
02786 if(rt == 0L) return;
02787 rt->rt.rtm.rtm_table = table;
02788 }
02789
02790 char *nic_route_get_table_name( int32_t table, char *buf, int len )
02791 {
02792 return rtnl_route_table2str( table, buf, len );
02793 }
02794
02795 extern
02796 int32_t nic_route_get_table_number( char *table )
02797 {
02798 return rtnl_route_str2table( table );
02799 }
02800
02801 uint8_t nic_route_get_family( IProute_t rt)
02802 {
02803 if( rt == 0L ) return 0;
02804
02805 return rt->rt.rtm.rtm_family;
02806 }
02807
02808 uint8_t nic_route_get_scope(IProute_t rt)
02809 {
02810 if( rt == 0L ) return 0;
02811 return rt->rt.rtm.rtm_scope;
02812 }
02813
02814 void nic_route_set_scope(IProute_t rt, uint8_t scope)
02815 {
02816 if( rt == 0L ) return;
02817 rt->rt.rtm.rtm_scope = scope;
02818 }
02819
02820 uint32_t nic_route_get_flags( IProute_t rt )
02821 {
02822 if( rt == 0L ) return 0;
02823 return rt->rt.rtm.rtm_flags;
02824 }
02825
02826 void nic_route_set_flags(IProute_t rt, uint32_t flags)
02827 {
02828 if( rt == 0L ) return;
02829 rt->rt.rtm.rtm_flags = flags;
02830 }
02831
02832 uint8_t nic_route_get_dst_len( IProute_t rt )
02833 {
02834 if( rt == 0L ) return 0;
02835 return rt->rt.rtm.rtm_dst_len;
02836 }
02837
02838 void nic_route_set_dst_len( IProute_t rt, uint8_t dst_len )
02839 {
02840 if( rt == 0L ) return;
02841 rt->rt.rtm.rtm_dst_len = dst_len;
02842 }
02843
02844 uint8_t nic_route_get_src_len( IProute_t rt )
02845 {
02846 if( rt == 0L ) return 0;
02847 return rt->rt.rtm.rtm_src_len;
02848 }
02849
02850 void nic_route_set_src_len( IProute_t rt, uint8_t src_len )
02851 {
02852 if( rt == 0L ) return;
02853 rt->rt.rtm.rtm_src_len = src_len;
02854 }
02855
02856 uint8_t nic_route_get_type( IProute_t rt)
02857 {
02858 if( rt == 0L ) return 0;
02859 return rt->rt.rtm.rtm_type;
02860 }
02861
02862 void nic_route_set_type( IProute_t rt, uint8_t type )
02863 {
02864 if( rt == 0L ) return;
02865 rt->rt.rtm.rtm_type = type;
02866 }
02867
02868 uint8_t nic_route_get_protocol( IProute_t rt)
02869 {
02870 if( rt == 0L ) return 0;
02871 return rt->rt.rtm.rtm_protocol;
02872 }
02873
02874 void nic_route_set_protocol( IProute_t rt, uint8_t protocol )
02875 {
02876 if( rt == 0L ) return;
02877 rt->rt.rtm.rtm_protocol = protocol;
02878 }
02879
02880 uint8_t nic_route_get_tos( IProute_t rt)
02881 {
02882 if( rt == 0L ) return 0;
02883 return rt->rt.rtm.rtm_tos;
02884 }
02885
02886 void nic_route_set_tos( IProute_t rt, uint8_t tos )
02887 {
02888 if( rt == 0L ) return;
02889 rt->rt.rtm.rtm_protocol = tos;
02890 }
02891
02892 ip_addr_t nic_route_get_dst( IProute_t rt )
02893 {
02894 ip_addr_t ip;
02895 memset(&ip,'\0',sizeof(ip));
02896 if( ( rt == 0L )
02897 ||((rt->rt.have & NIC_RT_DST)==0)
02898 ) return ip;
02899 return rt->rt.dst;
02900 }
02901
02902 void nic_route_set_dst( IProute_t rt, ip_addr_t ip)
02903 {
02904 if( rt == 0L ) return;
02905 rt->rt.dst = ip;
02906 rt->rt.have |= NIC_RT_DST;
02907 }
02908
02909 ip_addr_t nic_route_get_gateway( IProute_t rt )
02910 {
02911 ip_addr_t ip;
02912 memset(&ip,'\0',sizeof(ip));
02913 if( ( rt == 0L )
02914 ||((rt->rt.have & NIC_RT_GATEWAY)==0)
02915 ) return ip;
02916 return rt->rt.gw;
02917 }
02918
02919 void nic_route_set_gateway( IProute_t rt, ip_addr_t ip)
02920 {
02921 if( rt == 0L ) return;
02922 rt->rt.gw = ip;
02923 rt->rt.have |= NIC_RT_GATEWAY;
02924 }
02925
02926 ip_addr_t nic_route_get_src( IProute_t rt )
02927 {
02928 ip_addr_t ip;
02929 memset(&ip,'\0',sizeof(ip));
02930 if( ( rt == 0L )
02931 ||((rt->rt.have & NIC_RT_SRC)==0)
02932 ) return ip;
02933 return rt->rt.src;
02934 }
02935
02936 void nic_route_set_src( IProute_t rt, ip_addr_t ip)
02937 {
02938 if( rt == 0L ) return;
02939 rt->rt.src = ip;
02940 rt->rt.have |= NIC_RT_SRC;
02941 }
02942
02943 ip_addr_t nic_route_get_prefsrc( IProute_t rt )
02944 {
02945 ip_addr_t ip;
02946 memset(&ip,'\0',sizeof(ip));
02947 if( ( rt == 0L )
02948 ||((rt->rt.have & NIC_RT_PREFSRC)==0)
02949 ) return ip;
02950 return rt->rt.prefsrc;
02951 }
02952
02953 void nic_route_set_prefsrc( IProute_t rt, ip_addr_t ip)
02954 {
02955 if( rt == 0L ) return;
02956 rt->rt.prefsrc = ip;
02957 rt->rt.have |= NIC_RT_PREFSRC;
02958 }
02959
02960 int16_t nic_route_get_oif( IProute_t rt )
02961 {
02962 if( ( rt == 0L )
02963 ||((rt->rt.have & NIC_RT_OIF)==0)
02964 ) return -1;
02965
02966 return rt->rt.oif;
02967 }
02968
02969 void nic_route_set_oif( IProute_t rt, uint16_t oif)
02970 {
02971 if( rt == 0L ) return ;
02972
02973 rt->rt.oif = oif;
02974 rt->rt.have |= NIC_RT_OIF;
02975 }
02976
02977 NIC_if_name_t nic_route_get_iif( IProute_t rt )
02978 {
02979 NIC_if_name_t nil = { { '\0' } };
02980 if( ( rt == 0L )
02981 ||((rt->rt.have & NIC_RT_IIF) == 0 )
02982 ) return nil;
02983
02984 return *((NIC_if_name_t*)&(rt->rt.iif[0]));
02985 }
02986
02987 void nic_route_set_iif( IProute_t rt, char *iif )
02988 {
02989 if( rt == 0 ) return;
02990
02991 strncpy(&(rt->rt.iif[0]), iif, IFNAMSIZ);
02992 rt->rt.have |= NIC_RT_IIF;
02993 }
02994
02995 uint32_t nic_route_get_priority( IProute_t rt )
02996 {
02997 if( ( rt == 0L )
02998 ||((rt->rt.have & NIC_RT_PRIORITY) == 0 )
02999 ) return 0;
03000
03001 return rt->rt.priority;
03002 }
03003
03004 void nic_route_set_priority( IProute_t rt, uint32_t priority)
03005 {
03006 if( rt == 0L ) return;
03007
03008 rt->rt.priority = priority;
03009 rt->rt.have |= NIC_RT_PRIORITY;
03010 }
03011
03012 extern
03013 uint32_t nic_route_get_protoinfo(IProute_t rt)
03014 {
03015 if( ( rt == 0L )
03016 ||((rt->rt.have & NIC_RT_PROTOINFO) == 0 )
03017 ) return 0;
03018
03019 return rt->rt.protoinfo;
03020 }
03021
03022 extern
03023 void nic_route_set_protoinfo(IProute_t rt, uint32_t protoinfo)
03024 {
03025 if( rt == 0L ) return;
03026 rt->rt.protoinfo = protoinfo;
03027 rt->rt.have |= NIC_RT_PROTOINFO;
03028 }
03029
03030 uint32_t nic_route_get_session(IProute_t rt)
03031 {
03032 if( ( rt == 0L )
03033 ||((rt->rt.have & NIC_RT_SESSION) == 0 )
03034 ) return 0;
03035
03036 return rt->rt.session;
03037 }
03038
03039 extern
03040 void nic_route_set_session(IProute_t rt, uint32_t session)
03041 {
03042 if( rt == 0L ) return;
03043 rt->rt.session = session;
03044 rt->rt.have |= NIC_RT_SESSION;
03045 }
03046
03047 uint32_t nic_route_get_flow(IProute_t rt)
03048 {
03049 if( ( rt == 0L )
03050 ||((rt->rt.have & NIC_RT_FLOW) == 0 )
03051 ) return 0;
03052
03053 return rt->rt.flow;
03054 }
03055
03056 void nic_route_set_flow(IProute_t rt, uint32_t flow)
03057 {
03058 if( rt == 0L ) return;
03059 rt->rt.flow = flow;
03060 rt->rt.have |= NIC_RT_FLOW;
03061 }
03062
03063 uint32_t nic_route_get_mp_algo(IProute_t rt)
03064 {
03065 if( ( rt == 0L )
03066 ||((rt->rt.have & NIC_RT_MP_ALGO) == 0 )
03067 ) return 0;
03068
03069 return rt->rt.mp_algo;
03070 }
03071
03072 void nic_route_set_mp_algo(IProute_t rt, uint32_t mp_algo)
03073 {
03074 if( rt == 0L ) return;
03075 rt->rt.mp_algo = mp_algo;
03076 rt->rt.have |= NIC_RT_MP_ALGO;
03077 }
03078
03079 IProute_t nic_route_new
03080 ( NLH_t nh,
03081 int16_t oif,
03082 ip_addr_t *dst,
03083 uint8_t dst_len,
03084 ip_addr_t *gw,
03085 int8_t type,
03086 int8_t protocol,
03087 int8_t scope,
03088 int32_t priority,
03089 int32_t table,
03090 char* iif,
03091 ip_addr_t *src,
03092 uint8_t src_len
03093 )
03094 {
03095 if( ( dst && (dst->sa_family != AF_INET) && (dst->sa_family != AF_INET6))
03096 ||( gw && (gw->sa_family != AF_INET) && (gw->sa_family != AF_INET6))
03097 ||( src && (src->sa_family != AF_INET) && (src->sa_family != AF_INET6))
03098 )
03099 return 0L;
03100
03101 IProute_t rt = calloc(1, sizeof(struct nic_route_s));
03102
03103 if(rt == 0L)
03104 return rt;
03105
03106 rt->nh = nh;
03107
03108
03109 if ( dst == 0L )
03110 {
03111 dst_len = 0;
03112 table = RT_TABLE_MAIN;
03113 }else
03114 {
03115 rt->rt.rtm.rtm_dst_len = dst_len;
03116 rt->rt.dst = *dst;
03117 rt->rt.rtm.rtm_family = dst->sa_family;
03118 rt->rt.have |= NIC_RT_DST;
03119 }
03120
03121 if( gw )
03122 {
03123 rt->rt.gw = *gw;
03124 rt->rt.have |= NIC_RT_GATEWAY;
03125 if( rt->rt.rtm.rtm_family == 0 )
03126 rt->rt.rtm.rtm_family = rt->rt.gw.sa_family;
03127 }
03128
03129 if( scope == -1 )
03130 rt->rt.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
03131 else
03132 rt->rt.rtm.rtm_scope = scope;
03133
03134 if( table == -1 )
03135 rt->rt.rtm.rtm_table = RT_TABLE_LOCAL;
03136 else
03137 rt->rt.rtm.rtm_table = table;
03138
03139 if( type == -1 )
03140 rt->rt.rtm.rtm_type = RTN_UNICAST;
03141
03142 if( protocol == -1 )
03143 rt->rt.rtm.rtm_protocol = RTPROT_BOOT;
03144
03145 if( oif > -1 )
03146 {
03147 rt->rt.oif = oif;
03148 rt->rt.have |= NIC_RT_OIF;
03149 }
03150
03151 if( iif )
03152 {
03153 strncpy(&(rt->rt.iif[0]), iif, IFNAMSIZ);
03154 rt->rt.have |= NIC_RT_IIF;
03155 }
03156
03157 if( src && src_len )
03158 {
03159 rt->rt.src = *src;
03160 rt->rt.have |= NIC_RT_SRC;
03161 if( rt->rt.rtm.rtm_family == 0 )
03162 rt->rt.rtm.rtm_family = rt->rt.src.sa_family;
03163 }
03164
03165 if( priority > -1 )
03166 {
03167 rt->rt.priority = priority;
03168 rt->rt.have |= NIC_RT_PRIORITY;
03169 }
03170 return rt;
03171 }
03172
03173 static NIC_Res_t nic_route_msg( IProute_t rt, char *fn, char *tag, uint32_t msg_type, uint32_t msg_flags)
03174 {
03175
03176
03177 struct nl_msg *msg = nlmsg_build_simple(msg_type, msg_flags) ;
03178 if( msg == 0L )
03179 {
03180 if (rt->nh->eh)
03181 rt->nh->eh(rt->nh,NIC_ERR,"%s: failed to %s route - out of memory.", tag, fn);
03182 return NIC_FAIL;
03183 }
03184
03185 if ( nlmsg_append(msg, &(rt->rt.rtm), sizeof(struct rtmsg), 1) < 0 )
03186 goto nla_put_failure;
03187
03188 if( rt->rt.have & NIC_RT_OIF )
03189 NLA_PUT_U32(msg, RTA_OIF, rt->rt.oif);
03190
03191 if ( rt->rt.have & NIC_RT_DST )
03192 NLA_PUT(msg, RTA_DST, IP_ADDR_SIZE(&(rt->rt.dst)), IP_ADDR(&(rt->rt.dst)));
03193
03194 if ( rt->rt.have & NIC_RT_GATEWAY )
03195 NLA_PUT(msg, RTA_GATEWAY, IP_ADDR_SIZE(&(rt->rt.gw)), IP_ADDR(&(rt->rt.gw)));
03196
03197 if( rt->rt.have & NIC_RT_IIF )
03198 NLA_PUT_STRING(msg, RTA_IIF, &(rt->rt.iif[0]));
03199
03200 if ( rt->rt.have & NIC_RT_SRC )
03201 NLA_PUT(msg, RTA_SRC, IP_ADDR_SIZE(&(rt->rt.src)), IP_ADDR(&(rt->rt.src)));
03202
03203 if ( rt->rt.have & NIC_RT_PREFSRC )
03204 NLA_PUT(msg, RTA_SRC, IP_ADDR_SIZE(&(rt->rt.prefsrc)), IP_ADDR(&(rt->rt.prefsrc)));
03205
03206 if ( rt->rt.have & NIC_RT_PRIORITY )
03207 NLA_PUT_U32(msg, RTA_PRIORITY, rt->rt.priority);
03208
03209 if ( rt->rt.have & NIC_RT_FLOW )
03210 NLA_PUT_U32(msg, RTA_FLOW, rt->rt.flow);
03211
03212 if ( rt->rt.have & NIC_RT_SESSION )
03213 NLA_PUT_U32(msg, RTA_SESSION, rt->rt.session);
03214
03215 if ( rt->rt.have & NIC_RT_MP_ALGO )
03216 NLA_PUT_U32(msg, RTA_MP_ALGO, rt->rt.mp_algo);
03217
03218 if( nl_send_auto_complete(rt->nh->nl, nlmsg_hdr(msg)) < 0 )
03219 {
03220 if (rt->nh->eh)
03221 rt->nh->eh(rt->nh,NIC_ERR,"%s: send failed - %d %s", tag,
03222 nl_get_errno(), nl_geterror()
03223 );
03224 return NIC_FAIL;
03225 }
03226
03227 nlmsg_free(msg);
03228
03229 if( nl_wait_for_ack(rt->nh->nl) < 0 )
03230 {
03231 if (rt->nh->eh)
03232 rt->nh->eh(rt->nh,NIC_ERR,"%s: failed - %d: %s", tag,
03233 nl_get_errno(), nl_geterror()
03234 );
03235 return NIC_FAIL;
03236 }
03237
03238 return NIC_OK;
03239
03240 nla_put_failure:
03241
03242 if (rt->nh->eh)
03243 rt->nh->eh(rt->nh,NIC_ERR,"%s: failed to %s route - out of memory.", tag, fn);
03244 nlmsg_free(msg);
03245 return NIC_FAIL;
03246 }
03247
03248 NIC_Res_t nic_add_route( IProute_t rt )
03249 {
03250 if (rt == 0L) return NIC_FAIL;
03251
03252 return nic_route_msg( rt, "nic_add_route", "add", RTM_NEWROUTE, NLM_F_CREATE | NLM_F_REPLACE);
03253 }
03254
03255 NIC_Res_t nic_update_route( IProute_t rt )
03256 {
03257 if (rt == 0L) return NIC_FAIL;
03258
03259 return nic_route_msg( rt, "nic_update_route", "update", RTM_NEWROUTE, NLM_F_REPLACE);
03260 }
03261
03262 NIC_Res_t nic_remove_route( IProute_t rt )
03263 {
03264 if (rt == 0L) return NIC_FAIL;
03265
03266 return nic_route_msg( rt, "nic_remove_route", "remove", RTM_DELROUTE, 0);
03267 }
03268
03269 IProute_list_t *nic_route_list_new( IProute_t rt1, ... )
03270 {
03271 va_list va;
03272 va_start(va, rt1);
03273
03274 IProute_list_t *head = calloc(1,sizeof(IProute_list_t));
03275 IProute_list_node_t *n;
03276 IProute_t rt;
03277
03278 if( head == 0 )
03279 {
03280 va_end(va);
03281 if( rt1->nh->eh )
03282 rt1->nh->eh ( rt1->nh, NIC_ERR, "out of memory" );
03283 return 0;
03284 }
03285 rt=rt1;
03286 STAILQ_INIT(head);
03287 do
03288 {
03289 n = calloc(1,sizeof(IProute_list_node_t));
03290 if ( n == 0L )
03291 {
03292 va_end(va);
03293 free(head);
03294 if( rt->nh->eh )
03295 rt->nh->eh ( rt->nh, NIC_ERR, "out of memory" );
03296 return 0L;
03297 }
03298 n->route = rt;
03299 STAILQ_INSERT_TAIL( head, n, link );
03300 }while( (rt = va_arg(va, IProute_t)) != 0) ;
03301 va_end(va);
03302 return(head);
03303 }
03304
03305 void nic_route_list_free( IProute_list_t *head )
03306 {
03307 IProute_list_node_t *n, *a;
03308
03309 if ( !STAILQ_EMPTY(head) )
03310 {
03311 n = STAILQ_FIRST( head );
03312 do
03313 {
03314 a = STAILQ_NEXT(n, link);
03315 nic_route_free(n->route);
03316 free(n);
03317 n = a;
03318 }while (n);
03319 }
03320 }
03321
03322 NIC_Res_t nic_add_routes( IProute_list_t *head )
03323 {
03324 IProute_list_node_t *n;
03325 NIC_Res_t r;
03326 STAILQ_FOREACH(n,head,link)
03327 {
03328 if((r=nic_add_route(n->route)) == NIC_FAIL)
03329 return r;
03330 }
03331 return NIC_OK;
03332 }
03333
03334 NIC_Res_t nic_remove_routes( IProute_list_t *head )
03335 {
03336 IProute_list_node_t *n;
03337 NIC_Res_t r;
03338 STAILQ_FOREACH(n,head,link)
03339 {
03340 if((r=nic_remove_route(n->route))==NIC_FAIL)
03341 return r;
03342 }
03343 return NIC_OK;
03344 }
03345
03346 NIC_Res_t nic_update_routes( IProute_list_t *head )
03347 {
03348 IProute_list_node_t *n;
03349 NIC_Res_t r;
03350 STAILQ_FOREACH(n,head,link)
03351 {
03352 if((r=nic_update_route(n->route))==NIC_FAIL)
03353 return r;
03354 }
03355 return NIC_OK;
03356 }
03357
03358 void nic_route_free(void *rtp)
03359 {
03360 IProute_t rt = rtp;
03361
03362 if (!rt)
03363 return;
03364
03365 if( rt->nh->nic_route_tree )
03366 tdelete(rt, &(rt->nh->nic_route_tree), nic_route_comparator);
03367
03368 if( rt->rt.hops )
03369 free(rt->rt.hops);
03370
03371 free(rt);
03372 }
03373
03374 NIC_Res_t
03375 nic_configure_resolver
03376 (
03377 NLH_t nh,
03378 IPaddr_list_t *dns_servers,
03379 char *search_list
03380 )
03381 {
03382 if( (nh == 0) ||
03383 ( (dns_servers == 0L)
03384 && ((search_list==0L) || (*search_list =='\0'))
03385 )
03386 ) return NIC_OK;
03387 char tmpName[] = "/etc/XXXXXX";
03388 int fd, c;
03389 FILE *fop, *fip;
03390 IPaddr_list_node_t *n;
03391 char buf[8192], *p;
03392
03393 if( access("/etc/resolv.conf",W_OK) != 0 )
03394 return NIC_FAIL;
03395
03396 fd = mkstemp (&(tmpName[0]));
03397 if( fd == -1 )
03398 return NIC_FAIL;
03399
03400 if( (fop = fdopen(fd,"w")) == 0L )
03401 return NIC_FAIL;
03402
03403 fprintf(fop,"; resolv.conf generated by libdhcp\n");
03404
03405 if( (fip = fopen("/etc/resolv.conf","r")) != 0L )
03406 {
03407
03408 while( fscanf(fip,"%8191[^\n]", &(buf[0])) )
03409 {
03410 if( (p = strchr(buf,';')) != 0L )
03411 *p = '\0';
03412 p=buf + strspn(buf," \t");
03413 if( strncmp(p, "options",7) == 0 )
03414 fprintf(fop,"%s\n",p);
03415 while(((c=fgetc(fip))=='\n') && (c != EOF));
03416 if( c != EOF )
03417 ungetc(c,fip);
03418 else
03419 break;
03420 }
03421 fclose(fip);
03422 }
03423
03424 if( search_list && (*search_list != '\0'))
03425 fprintf(fop,"search %s\n", search_list);
03426
03427 STAILQ_FOREACH(n,dns_servers,link)
03428 {
03429 if( n->addr )
03430 fprintf(fop,"nameserver %s\n",ip_text_addr(&(n->addr->nla.addr),buf,64));
03431 }
03432 fflush(fop);
03433 fclose(fop);
03434 if( rename("/etc/resolv.conf", "/etc/resolv.conf.predhclient") != 0 )
03435 {
03436 unlink(tmpName);
03437 return NIC_FAIL;
03438 }
03439 if( rename(tmpName,"/etc/resolv.conf") != 0 )
03440 {
03441 unlink(tmpName);
03442 return NIC_FAIL;
03443 }
03444 chmod("/etc/resolv.conf",0644);
03445 return NIC_OK;
03446 }
03447
03448 extern
03449 NIC_Res_t
03450 nic_set_hostname
03451 ( NLH_t nh,
03452 char *hostname
03453 )
03454 {
03455 return sethostname(hostname, strlen(hostname)) == 0 ? NIC_OK : NIC_FAIL;
03456 }
03457
03458 NIC_Res_t
03459 nic_configure
03460 (
03461 NLH_t nh,
03462 NIC_t nic,
03463 IPaddr_list_t *addresses,
03464 IProute_list_t *routes,
03465 IPaddr_list_t *dns_servers,
03466 char *search_list,
03467 char *host_name
03468 )
03469 {
03470 if ( addresses && ( nic_add_addresses( nic, addresses ) == NIC_FAIL ))
03471 {
03472 if (nh->eh)
03473 nh->eh(nh, NIC_ERR, "nic_configure: failed to add addresses.");
03474 return NIC_FAIL;
03475 }
03476
03477 if ( routes && ( nic_add_routes( routes ) == NIC_FAIL ))
03478 {
03479 if (nh->eh)
03480 nh->eh(nh, NIC_ERR, "nic_configure: failed to add routes.");
03481 return NIC_FAIL;
03482 }
03483
03484 if ((search_list && *search_list) ||
03485 (dns_servers && !STAILQ_EMPTY(dns_servers))) {
03486 if (nic_configure_resolver(nh, dns_servers, search_list) == NIC_FAIL) {
03487 if (nh->eh)
03488 nh->eh(nh, NIC_ERR, "nic_configure: failed to configure resolver.");
03489 return NIC_FAIL;
03490 }
03491 }
03492 return NIC_OK;
03493 }
03494
03495
03496
03497