00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "config.h"
00010
00011 #include <sys/param.h>
00012 #include <sys/types.h>
00013 #include <sys/ioctl.h>
00014 #include <sys/socket.h>
00015 #ifdef HAVE_SYS_SOCKIO_H
00016 # include <sys/sockio.h>
00017 #endif
00018
00019 #ifndef IP_MULTICAST
00020 # define IP_MULTICAST
00021 #endif
00022 #include <net/if.h>
00023 #ifdef HAVE_NET_IF_VAR_H
00024 # include <net/if_var.h>
00025 #endif
00026 #undef IP_MULTICAST
00027
00028 #ifdef HAVE_NETINET_IN_VAR_H
00029 # include <netinet/in.h>
00030 # include <netinet/in_var.h>
00031 #endif
00032
00033 #include <errno.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <unistd.h>
00038
00039 #include "dnet.h"
00040
00041
00042 #if defined(SIOCRIPMTU) && defined(SIOCSIPMTU)
00043 # define SIOCGIFMTU SIOCRIPMTU
00044 # define SIOCSIFMTU SIOCSIPMTU
00045 #endif
00046
00047
00048 #if defined(SIOCADDIFADDR) && defined(SIOCDELIFADDR)
00049 # define SIOCAIFADDR SIOCADDIFADDR
00050 # define SIOCDIFADDR SIOCDELIFADDR
00051 #endif
00052
00053
00054 #if !defined(ifr_mtu) && defined(ifr_metric)
00055 # define ifr_mtu ifr_metric
00056 #endif
00057
00058 #ifdef HAVE_SOCKADDR_SA_LEN
00059 # define NEXTIFR(i) ((struct ifreq *)((u_char *)&i->ifr_addr + \
00060 (i->ifr_addr.sa_len ? i->ifr_addr.sa_len : \
00061 sizeof(i->ifr_addr))))
00062 #else
00063 # define NEXTIFR(i) (i + 1)
00064 #endif
00065
00066
00067 struct dnet_ifaliasreq {
00068 char ifra_name[IFNAMSIZ];
00069 struct sockaddr ifra_addr;
00070 struct sockaddr ifra_brdaddr;
00071 struct sockaddr ifra_mask;
00072 int ifra_cookie;
00073 };
00074
00075 struct intf_handle {
00076 int fd;
00077 int fd6;
00078 struct ifconf ifc;
00079 u_char ifcbuf[4192];
00080 };
00081
00082 static int
00083 intf_flags_to_iff(u_short flags, int iff)
00084 {
00085 if (flags & INTF_FLAG_UP)
00086 iff |= IFF_UP;
00087 else
00088 iff &= ~IFF_UP;
00089 if (flags & INTF_FLAG_NOARP)
00090 iff |= IFF_NOARP;
00091 else
00092 iff &= ~IFF_NOARP;
00093
00094 return (iff);
00095 }
00096
00097 static u_int
00098 intf_iff_to_flags(int iff)
00099 {
00100 u_int n = 0;
00101
00102 if (iff & IFF_UP)
00103 n |= INTF_FLAG_UP;
00104 if (iff & IFF_LOOPBACK)
00105 n |= INTF_FLAG_LOOPBACK;
00106 if (iff & IFF_POINTOPOINT)
00107 n |= INTF_FLAG_POINTOPOINT;
00108 if (iff & IFF_NOARP)
00109 n |= INTF_FLAG_NOARP;
00110 if (iff & IFF_BROADCAST)
00111 n |= INTF_FLAG_BROADCAST;
00112 if (iff & IFF_MULTICAST)
00113 n |= INTF_FLAG_MULTICAST;
00114
00115 return (n);
00116 }
00117
00118 intf_t *
00119 intf_open(void)
00120 {
00121 intf_t *intf;
00122
00123 if ((intf = calloc(1, sizeof(*intf))) != NULL) {
00124 intf->fd = intf->fd6 = -1;
00125
00126 if ((intf->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00127 return (intf_close(intf));
00128 #ifdef SIOCGIFNETMASK_IN6
00129 if ((intf->fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
00130 # ifdef EPROTONOSUPPORT
00131 if (errno != EPROTONOSUPPORT)
00132 # endif
00133 return (intf_close(intf));
00134 }
00135 #endif
00136 }
00137 return (intf);
00138 }
00139
00140 static int
00141 _intf_delete_addrs(intf_t *intf, struct intf_entry *entry)
00142 {
00143 #if defined(SIOCDIFADDR)
00144 struct dnet_ifaliasreq ifra;
00145
00146 memset(&ifra, 0, sizeof(ifra));
00147 strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
00148 if (entry->intf_addr.addr_type == ADDR_TYPE_IP) {
00149 addr_ntos(&entry->intf_addr, &ifra.ifra_addr);
00150 ioctl(intf->fd, SIOCDIFADDR, &ifra);
00151 }
00152 if (entry->intf_dst_addr.addr_type == ADDR_TYPE_IP) {
00153 addr_ntos(&entry->intf_dst_addr, &ifra.ifra_addr);
00154 ioctl(intf->fd, SIOCDIFADDR, &ifra);
00155 }
00156 #elif defined(SIOCLIFREMOVEIF)
00157 struct ifreq ifr;
00158
00159 memset(&ifr, 0, sizeof(ifr));
00160 strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
00161
00162 ioctl(intf->fd, SIOCLIFREMOVEIF, &ifr);
00163 #endif
00164 return (0);
00165 }
00166
00167 static int
00168 _intf_delete_aliases(intf_t *intf, struct intf_entry *entry)
00169 {
00170 int i;
00171 #if defined(SIOCDIFADDR) && !defined(__linux__)
00172 struct dnet_ifaliasreq ifra;
00173
00174 memset(&ifra, 0, sizeof(ifra));
00175 strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
00176
00177 for (i = 0; i < (int)entry->intf_alias_num; i++) {
00178 addr_ntos(&entry->intf_alias_addrs[i], &ifra.ifra_addr);
00179 ioctl(intf->fd, SIOCDIFADDR, &ifra);
00180 }
00181 #else
00182 struct ifreq ifr;
00183
00184 for (i = 0; i < entry->intf_alias_num; i++) {
00185 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s:%d",
00186 entry->intf_name, i + 1);
00187 # ifdef SIOCLIFREMOVEIF
00188
00189 ioctl(intf->fd, SIOCLIFREMOVEIF, &ifr);
00190 # else
00191
00192 ifr.ifr_flags = 0;
00193 ioctl(intf->fd, SIOCSIFFLAGS, &ifr);
00194 # endif
00195 }
00196 #endif
00197 return (0);
00198 }
00199
00200 static int
00201 _intf_add_aliases(intf_t *intf, const struct intf_entry *entry)
00202 {
00203 int i;
00204 #ifdef SIOCAIFADDR
00205 struct dnet_ifaliasreq ifra;
00206 struct addr bcast;
00207
00208 memset(&ifra, 0, sizeof(ifra));
00209 strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
00210
00211 for (i = 0; i < (int)entry->intf_alias_num; i++) {
00212 if (entry->intf_alias_addrs[i].addr_type != ADDR_TYPE_IP)
00213 continue;
00214
00215 if (addr_ntos(&entry->intf_alias_addrs[i],
00216 &ifra.ifra_addr) < 0)
00217 return (-1);
00218 addr_bcast(&entry->intf_alias_addrs[i], &bcast);
00219 addr_ntos(&bcast, &ifra.ifra_brdaddr);
00220 addr_btos(entry->intf_alias_addrs[i].addr_bits,
00221 &ifra.ifra_mask);
00222
00223 if (ioctl(intf->fd, SIOCAIFADDR, &ifra) < 0)
00224 return (-1);
00225 }
00226 #else
00227 struct ifreq ifr;
00228 int n = 1;
00229
00230 for (i = 0; i < entry->intf_alias_num; i++) {
00231 if (entry->intf_alias_addrs[i].addr_type != ADDR_TYPE_IP)
00232 continue;
00233
00234 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s:%d",
00235 entry->intf_name, n++);
00236 # ifdef SIOCLIFADDIF
00237 if (ioctl(intf->fd, SIOCLIFADDIF, &ifr) < 0)
00238 return (-1);
00239 # endif
00240 if (addr_ntos(&entry->intf_alias_addrs[i], &ifr.ifr_addr) < 0)
00241 return (-1);
00242 if (ioctl(intf->fd, SIOCSIFADDR, &ifr) < 0)
00243 return (-1);
00244 }
00245 strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
00246 #endif
00247 return (0);
00248 }
00249
00250 int
00251 intf_set(intf_t *intf, const struct intf_entry *entry)
00252 {
00253 struct ifreq ifr;
00254 struct intf_entry *orig;
00255 struct addr bcast;
00256 u_char buf[BUFSIZ];
00257
00258 orig = (struct intf_entry *)buf;
00259 orig->intf_len = sizeof(buf);
00260 strcpy(orig->intf_name, entry->intf_name);
00261
00262 if (intf_get(intf, orig) < 0)
00263 return (-1);
00264
00265
00266 if (_intf_delete_aliases(intf, orig) < 0)
00267 return (-1);
00268
00269
00270 if (_intf_delete_addrs(intf, orig) < 0)
00271 return (-1);
00272
00273 memset(&ifr, 0, sizeof(ifr));
00274 strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
00275
00276
00277 if (entry->intf_mtu != 0) {
00278 ifr.ifr_mtu = entry->intf_mtu;
00279 if (ioctl(intf->fd, SIOCSIFMTU, &ifr) < 0)
00280 return (-1);
00281 }
00282
00283 if (entry->intf_addr.addr_type == ADDR_TYPE_IP) {
00284 #ifdef BSD
00285
00286 if (addr_btos(entry->intf_addr.addr_bits,
00287 &ifr.ifr_addr) == 0) {
00288 if (ioctl(intf->fd, SIOCSIFNETMASK, &ifr) < 0)
00289 return (-1);
00290 }
00291 #endif
00292 if (addr_ntos(&entry->intf_addr, &ifr.ifr_addr) < 0)
00293 return (-1);
00294 if (ioctl(intf->fd, SIOCSIFADDR, &ifr) < 0 && errno != EEXIST)
00295 return (-1);
00296
00297 if (addr_btos(entry->intf_addr.addr_bits, &ifr.ifr_addr) == 0
00298 #ifdef __linux__
00299 && entry->intf_addr.addr_ip != 0
00300 #endif
00301 ) {
00302 if (ioctl(intf->fd, SIOCSIFNETMASK, &ifr) < 0)
00303 return (-1);
00304 }
00305 if (addr_bcast(&entry->intf_addr, &bcast) == 0) {
00306 if (addr_ntos(&bcast, &ifr.ifr_broadaddr) == 0) {
00307
00308 ioctl(intf->fd, SIOCSIFBRDADDR, &ifr);
00309 }
00310 }
00311 }
00312
00313 if (entry->intf_link_addr.addr_type == ADDR_TYPE_ETH &&
00314 addr_cmp(&entry->intf_link_addr, &orig->intf_link_addr) != 0) {
00315 #if defined(SIOCSIFHWADDR)
00316 if (addr_ntos(&entry->intf_link_addr, &ifr.ifr_hwaddr) < 0)
00317 return (-1);
00318 if (ioctl(intf->fd, SIOCSIFHWADDR, &ifr) < 0)
00319 return (-1);
00320 #elif defined (SIOCSIFLLADDR)
00321 memcpy(ifr.ifr_addr.sa_data, &entry->intf_link_addr.addr_eth,
00322 ETH_ADDR_LEN);
00323 ifr.ifr_addr.sa_len = ETH_ADDR_LEN;
00324 if (ioctl(intf->fd, SIOCSIFLLADDR, &ifr) < 0)
00325 return (-1);
00326 #else
00327 eth_t *eth;
00328
00329 if ((eth = eth_open(entry->intf_name)) == NULL)
00330 return (-1);
00331 if (eth_set(eth, &entry->intf_link_addr.addr_eth) < 0) {
00332 eth_close(eth);
00333 return (-1);
00334 }
00335 eth_close(eth);
00336 #endif
00337 }
00338
00339 if (entry->intf_dst_addr.addr_type == ADDR_TYPE_IP) {
00340 if (addr_ntos(&entry->intf_dst_addr, &ifr.ifr_dstaddr) < 0)
00341 return (-1);
00342 if (ioctl(intf->fd, SIOCSIFDSTADDR, &ifr) < 0 &&
00343 errno != EEXIST)
00344 return (-1);
00345 }
00346
00347 if (_intf_add_aliases(intf, entry) < 0)
00348 return (-1);
00349
00350
00351 if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0)
00352 return (-1);
00353
00354 ifr.ifr_flags = intf_flags_to_iff(entry->intf_flags, ifr.ifr_flags);
00355
00356 if (ioctl(intf->fd, SIOCSIFFLAGS, &ifr) < 0)
00357 return (-1);
00358
00359 return (0);
00360 }
00361
00362
00363 static void
00364 _intf_set_type(struct intf_entry *entry)
00365 {
00366 if ((entry->intf_flags & INTF_FLAG_BROADCAST) != 0)
00367 entry->intf_type = INTF_TYPE_ETH;
00368 else if ((entry->intf_flags & INTF_FLAG_POINTOPOINT) != 0)
00369 entry->intf_type = INTF_TYPE_TUN;
00370 else if ((entry->intf_flags & INTF_FLAG_LOOPBACK) != 0)
00371 entry->intf_type = INTF_TYPE_LOOPBACK;
00372 else
00373 entry->intf_type = INTF_TYPE_OTHER;
00374 }
00375
00376 static int
00377 _intf_get_noalias(intf_t *intf, struct intf_entry *entry)
00378 {
00379 struct ifreq ifr;
00380
00381 strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
00382
00383
00384 if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0)
00385 return (-1);
00386
00387 entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags);
00388 _intf_set_type(entry);
00389
00390
00391 if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0)
00392 return (-1);
00393 entry->intf_mtu = ifr.ifr_mtu;
00394
00395 entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type =
00396 entry->intf_link_addr.addr_type = ADDR_TYPE_NONE;
00397
00398
00399 if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) {
00400 addr_ston(&ifr.ifr_addr, &entry->intf_addr);
00401 if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0)
00402 return (-1);
00403 addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits);
00404 }
00405
00406 if (entry->intf_type == INTF_TYPE_TUN) {
00407 if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) {
00408 if (addr_ston(&ifr.ifr_addr,
00409 &entry->intf_dst_addr) < 0)
00410 return (-1);
00411 }
00412 } else if (entry->intf_type == INTF_TYPE_ETH) {
00413 #if defined(SIOCGIFHWADDR)
00414 if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0)
00415 return (-1);
00416 if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0)
00417 return (-1);
00418 #elif defined(SIOCRPHYSADDR)
00419
00420 struct ifdevea *ifd = (struct ifdevea *)𝔦
00421
00422 if (ioctl(intf->fd, SIOCRPHYSADDR, ifd) < 0)
00423 return (-1);
00424 addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS,
00425 ifd->current_pa, ETH_ADDR_LEN);
00426 #else
00427 eth_t *eth;
00428
00429 if ((eth = eth_open(entry->intf_name)) != NULL) {
00430 if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) {
00431 entry->intf_link_addr.addr_type =
00432 ADDR_TYPE_ETH;
00433 entry->intf_link_addr.addr_bits =
00434 ETH_ADDR_BITS;
00435 }
00436 eth_close(eth);
00437 }
00438 #endif
00439 }
00440 return (0);
00441 }
00442
00443 #ifdef SIOCLIFADDR
00444
00445 static int
00446 _intf_get_aliases(intf_t *intf, struct intf_entry *entry)
00447 {
00448 struct dnet_ifaliasreq ifra;
00449 struct addr *ap, *lap;
00450
00451 strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
00452 addr_ntos(&entry->intf_addr, &ifra.ifra_addr);
00453 addr_btos(entry->intf_addr.addr_bits, &ifra.ifra_mask);
00454 memset(&ifra.ifra_brdaddr, 0, sizeof(ifra.ifra_brdaddr));
00455 ifra.ifra_cookie = 1;
00456
00457 ap = entry->intf_alias_addrs;
00458 lap = (struct addr *)((u_char *)entry + entry->intf_len);
00459
00460 while (ioctl(intf->fd, SIOCLIFADDR, &ifra) == 0 &&
00461 ifra.ifra_cookie > 0 && (ap + 1) < lap) {
00462 if (addr_ston(&ifra.ifra_addr, ap) < 0)
00463 break;
00464 ap++, entry->intf_alias_num++;
00465 }
00466 entry->intf_len = (u_char *)ap - (u_char *)entry;
00467
00468 return (0);
00469 }
00470 #else
00471 static int
00472 _intf_get_aliases(intf_t *intf, struct intf_entry *entry)
00473 {
00474 struct ifreq *ifr, *lifr;
00475 struct addr *ap, *lap;
00476 char *p;
00477
00478 if (intf->ifc.ifc_len < (int)sizeof(*ifr)) {
00479 errno = EINVAL;
00480 return (-1);
00481 }
00482 entry->intf_alias_num = 0;
00483 ap = entry->intf_alias_addrs;
00484 lifr = (struct ifreq *)intf->ifc.ifc_buf +
00485 (intf->ifc.ifc_len / sizeof(*lifr));
00486 lap = (struct addr *)((u_char *)entry + entry->intf_len);
00487
00488
00489 for (ifr = intf->ifc.ifc_req; ifr < lifr && (ap + 1) < lap;
00490 ifr = NEXTIFR(ifr)) {
00491
00492 if ((p = strchr(ifr->ifr_name, ':')) != NULL)
00493 *p = '\0';
00494
00495 if (strcmp(ifr->ifr_name, entry->intf_name) != 0)
00496 continue;
00497
00498 if (addr_ston(&ifr->ifr_addr, ap) < 0)
00499 continue;
00500
00501
00502 if (ap->addr_type == ADDR_TYPE_ETH) {
00503 memcpy(&entry->intf_link_addr, ap, sizeof(*ap));
00504 continue;
00505 } else if (ap->addr_type == ADDR_TYPE_IP) {
00506 if (ap->addr_ip == entry->intf_addr.addr_ip ||
00507 ap->addr_ip == entry->intf_dst_addr.addr_ip)
00508 continue;
00509 }
00510 #ifdef SIOCGIFNETMASK_IN6
00511 else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
00512 struct in6_ifreq ifr6;
00513
00514
00515 memcpy(&ifr6, ifr, sizeof(ifr6));
00516
00517 if (ioctl(intf->fd6, SIOCGIFNETMASK_IN6, &ifr6) == 0) {
00518 addr_stob((struct sockaddr *)&ifr6.ifr_addr,
00519 &ap->addr_bits);
00520 }
00521 else perror("SIOCGIFNETMASK_IN6");
00522 }
00523 #endif
00524 ap++, entry->intf_alias_num++;
00525 }
00526 #ifdef HAVE_LINUX_PROCFS
00527 #define PROC_INET6_FILE "/proc/net/if_inet6"
00528 {
00529 FILE *f;
00530 char buf[256], s[8][5], name[INTF_NAME_LEN];
00531 u_int idx, bits, scope, flags;
00532
00533 if ((f = fopen(PROC_INET6_FILE, "r")) != NULL) {
00534 while (ap < lap &&
00535 fgets(buf, sizeof(buf), f) != NULL) {
00536 sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %02x %02x %02x %02x %32s\n",
00537 s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
00538 &idx, &bits, &scope, &flags, name);
00539 if (strcmp(name, entry->intf_name) == 0) {
00540 snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
00541 s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], bits);
00542 addr_aton(buf, ap);
00543 ap++, entry->intf_alias_num++;
00544 }
00545 }
00546 fclose(f);
00547 }
00548 }
00549 #endif
00550 entry->intf_len = (u_char *)ap - (u_char *)entry;
00551
00552 return (0);
00553 }
00554 #endif
00555
00556 int
00557 intf_get(intf_t *intf, struct intf_entry *entry)
00558 {
00559 if (_intf_get_noalias(intf, entry) < 0)
00560 return (-1);
00561 #ifndef SIOCLIFADDR
00562 intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf;
00563 intf->ifc.ifc_len = sizeof(intf->ifcbuf);
00564
00565 if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0)
00566 return (-1);
00567 #endif
00568 return (_intf_get_aliases(intf, entry));
00569 }
00570
00571 static int
00572 _match_intf_src(const struct intf_entry *entry, void *arg)
00573 {
00574 struct intf_entry *save = (struct intf_entry *)arg;
00575
00576 if (entry->intf_addr.addr_type == ADDR_TYPE_IP &&
00577 entry->intf_addr.addr_ip == save->intf_addr.addr_ip) {
00578
00579 if (save->intf_len < entry->intf_len)
00580 memcpy(save, entry, save->intf_len);
00581 else
00582 memcpy(save, entry, entry->intf_len);
00583 return (1);
00584 }
00585 return (0);
00586 }
00587
00588 int
00589 intf_get_src(intf_t *intf, struct intf_entry *entry, struct addr *src)
00590 {
00591 memcpy(&entry->intf_addr, src, sizeof(*src));
00592
00593 if (intf_loop(intf, _match_intf_src, entry) != 1) {
00594 errno = ENXIO;
00595 return (-1);
00596 }
00597 return (0);
00598 }
00599
00600 int
00601 intf_get_dst(intf_t *intf, struct intf_entry *entry, struct addr *dst)
00602 {
00603 struct sockaddr_in sin;
00604 int n;
00605
00606 if (dst->addr_type != ADDR_TYPE_IP) {
00607 errno = EINVAL;
00608 return (-1);
00609 }
00610 addr_ntos(dst, (struct sockaddr *)&sin);
00611 sin.sin_port = htons(666);
00612
00613 if (connect(intf->fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
00614 return (-1);
00615
00616 n = sizeof(sin);
00617 if (getsockname(intf->fd, (struct sockaddr *)&sin, &n) < 0)
00618 return (-1);
00619
00620 addr_ston((struct sockaddr *)&sin, &entry->intf_addr);
00621
00622 if (intf_loop(intf, _match_intf_src, entry) != 1)
00623 return (-1);
00624
00625 return (0);
00626 }
00627
00628 #ifdef HAVE_LINUX_PROCFS
00629 #define PROC_DEV_FILE "/proc/net/dev"
00630
00631 int
00632 intf_loop(intf_t *intf, intf_handler callback, void *arg)
00633 {
00634 FILE *fp;
00635 struct intf_entry *entry;
00636 char *p, buf[BUFSIZ], ebuf[BUFSIZ];
00637 int ret;
00638
00639 entry = (struct intf_entry *)ebuf;
00640
00641 if ((fp = fopen(PROC_DEV_FILE, "r")) == NULL)
00642 return (-1);
00643
00644 intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf;
00645 intf->ifc.ifc_len = sizeof(intf->ifcbuf);
00646
00647 if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0)
00648 return (-1);
00649
00650 ret = 0;
00651 while (fgets(buf, sizeof(buf), fp) != NULL) {
00652 if ((p = strchr(buf, ':')) == NULL)
00653 continue;
00654 *p = '\0';
00655 for (p = buf; *p == ' '; p++)
00656 ;
00657
00658 memset(ebuf, 0, sizeof(ebuf));
00659 strlcpy(entry->intf_name, p, sizeof(entry->intf_name));
00660 entry->intf_len = sizeof(ebuf);
00661
00662 if (_intf_get_noalias(intf, entry) < 0) {
00663 ret = -1;
00664 break;
00665 }
00666 if (_intf_get_aliases(intf, entry) < 0) {
00667 ret = -1;
00668 break;
00669 }
00670 if ((ret = (*callback)(entry, arg)) != 0)
00671 break;
00672 }
00673 if (ferror(fp))
00674 ret = -1;
00675
00676 fclose(fp);
00677
00678 return (ret);
00679 }
00680 #else
00681 int
00682 intf_loop(intf_t *intf, intf_handler callback, void *arg)
00683 {
00684 struct intf_entry *entry;
00685 struct ifreq *ifr, *lifr, *pifr;
00686 char *p, ebuf[BUFSIZ];
00687 int ret;
00688
00689 entry = (struct intf_entry *)ebuf;
00690
00691 intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf;
00692 intf->ifc.ifc_len = sizeof(intf->ifcbuf);
00693
00694 if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0)
00695 return (-1);
00696
00697 pifr = NULL;
00698 lifr = (struct ifreq *)&intf->ifc.ifc_buf[intf->ifc.ifc_len];
00699
00700 for (ifr = intf->ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr)) {
00701
00702 if ((p = strchr(ifr->ifr_name, ':')) != NULL)
00703 *p = '\0';
00704
00705 if (pifr != NULL && strcmp(ifr->ifr_name, pifr->ifr_name) == 0)
00706 continue;
00707
00708 memset(ebuf, 0, sizeof(ebuf));
00709 strlcpy(entry->intf_name, ifr->ifr_name,
00710 sizeof(entry->intf_name));
00711 entry->intf_len = sizeof(ebuf);
00712
00713 if (_intf_get_noalias(intf, entry) < 0)
00714 return (-1);
00715 if (_intf_get_aliases(intf, entry) < 0)
00716 return (-1);
00717
00718 if ((ret = (*callback)(entry, arg)) != 0)
00719 return (ret);
00720
00721 pifr = ifr;
00722 }
00723 return (0);
00724 }
00725 #endif
00726
00727 intf_t *
00728 intf_close(intf_t *intf)
00729 {
00730 if (intf != NULL) {
00731 if (intf->fd >= 0)
00732 close(intf->fd);
00733 if (intf->fd6 >= 0)
00734 close(intf->fd6);
00735 free(intf);
00736 }
00737 return (NULL);
00738 }