1*28b8bcf0Sflorian /* $OpenBSD: interface.c,v 1.17 2024/08/21 14:58:14 florian Exp $ */ 2ddeeec14Snorby 3ddeeec14Snorby /* 4ddeeec14Snorby * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> 5ddeeec14Snorby * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6ddeeec14Snorby * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 7ddeeec14Snorby * 8ddeeec14Snorby * Permission to use, copy, modify, and distribute this software for any 9ddeeec14Snorby * purpose with or without fee is hereby granted, provided that the above 10ddeeec14Snorby * copyright notice and this permission notice appear in all copies. 11ddeeec14Snorby * 12ddeeec14Snorby * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13ddeeec14Snorby * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14ddeeec14Snorby * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15ddeeec14Snorby * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16ddeeec14Snorby * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17ddeeec14Snorby * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18ddeeec14Snorby * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19ddeeec14Snorby */ 20ddeeec14Snorby 21ddeeec14Snorby #include <sys/types.h> 22ddeeec14Snorby #include <sys/ioctl.h> 23ddeeec14Snorby #include <sys/time.h> 24ddeeec14Snorby #include <sys/socket.h> 25ddeeec14Snorby #include <netinet/in.h> 26ddeeec14Snorby #include <arpa/inet.h> 27ddeeec14Snorby #include <net/if.h> 28ddeeec14Snorby #include <net/if_types.h> 29ddeeec14Snorby #include <ctype.h> 30ddeeec14Snorby #include <err.h> 31ddeeec14Snorby #include <stdio.h> 32ddeeec14Snorby #include <stdlib.h> 33ddeeec14Snorby #include <unistd.h> 34ddeeec14Snorby #include <string.h> 35ddeeec14Snorby #include <event.h> 36ddeeec14Snorby 37ddeeec14Snorby #include "ripd.h" 38ddeeec14Snorby #include "log.h" 39ddeeec14Snorby #include "rip.h" 40ddeeec14Snorby #include "rde.h" 41ddeeec14Snorby #include "ripe.h" 42ddeeec14Snorby 43ddeeec14Snorby extern struct ripd_conf *conf; 44ddeeec14Snorby 45ddeeec14Snorby int if_act_start(struct iface *); 46ddeeec14Snorby int if_act_reset(struct iface *); 47ddeeec14Snorby 48ddeeec14Snorby struct { 49ddeeec14Snorby int state; 50ddeeec14Snorby enum iface_event event; 51ddeeec14Snorby enum iface_action action; 52ddeeec14Snorby int new_state; 53ddeeec14Snorby } iface_fsm[] = { 54ddeeec14Snorby /* current state event that happened action to take resulting state */ 55ddeeec14Snorby {IF_STA_DOWN, IF_EVT_UP, IF_ACT_STRT, 0}, 56ddeeec14Snorby {IF_STA_ANY, IF_EVT_DOWN, IF_ACT_RST, IF_STA_DOWN}, 57ddeeec14Snorby {-1, IF_EVT_NOTHING, IF_ACT_NOTHING, 0}, 58ddeeec14Snorby }; 59ddeeec14Snorby 60ddeeec14Snorby const char * const if_action_names[] = { 61ddeeec14Snorby "NOTHING", 62ddeeec14Snorby "START", 63ddeeec14Snorby "RESET" 64ddeeec14Snorby }; 65ddeeec14Snorby 66ddeeec14Snorby static const char * const if_event_names[] = { 67ddeeec14Snorby "NOTHING", 68ddeeec14Snorby "UP", 69ddeeec14Snorby "DOWN", 70ddeeec14Snorby }; 71ddeeec14Snorby 72ddeeec14Snorby void 73ddeeec14Snorby if_init(struct ripd_conf *xconf, struct iface *iface) 74ddeeec14Snorby { 750ab89b34Smichele struct ifreq ifr; 760ab89b34Smichele u_int rdomain; 770ab89b34Smichele 78ddeeec14Snorby /* XXX as in ospfd I would like to kill that. This is a design error */ 79ddeeec14Snorby iface->fd = xconf->rip_socket; 804d8b14b6Smichele 810ab89b34Smichele strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 828bb39f08Sguenther if (ioctl(iface->fd, SIOCGIFRDOMAIN, (caddr_t)&ifr) == -1) 830ab89b34Smichele rdomain = 0; 840ab89b34Smichele else { 850ab89b34Smichele rdomain = ifr.ifr_rdomainid; 8613ae2b57Smikeb if (setsockopt(iface->fd, SOL_SOCKET, SO_RTABLE, &rdomain, 870ab89b34Smichele sizeof(rdomain)) == -1) 880ab89b34Smichele fatal("failed to set rdomain"); 890ab89b34Smichele } 900ab89b34Smichele if (rdomain != xconf->rdomain) 910ab89b34Smichele fatalx("interface rdomain mismatch"); 920ab89b34Smichele 934d8b14b6Smichele ripe_demote_iface(iface, 0); 94ddeeec14Snorby } 95ddeeec14Snorby 96ddeeec14Snorby int 97ddeeec14Snorby if_fsm(struct iface *iface, enum iface_event event) 98ddeeec14Snorby { 99ddeeec14Snorby int old_state; 100ddeeec14Snorby int new_state = 0; 101ddeeec14Snorby int i, ret = 0; 102ddeeec14Snorby 103ddeeec14Snorby old_state = iface->state; 104ddeeec14Snorby 105ddeeec14Snorby for (i = 0; iface_fsm[i].state != -1; i++) 106ddeeec14Snorby if ((iface_fsm[i].state & old_state) && 107ddeeec14Snorby (iface_fsm[i].event == event)) { 108ddeeec14Snorby new_state = iface_fsm[i].new_state; 109ddeeec14Snorby break; 110ddeeec14Snorby } 111ddeeec14Snorby 112ddeeec14Snorby if (iface_fsm[i].state == -1) { 113ddeeec14Snorby /* event outside of the defined fsm, ignore it. */ 114ddeeec14Snorby log_debug("if_fsm: interface %s, " 115ddeeec14Snorby "event '%s' not expected in state '%s'", iface->name, 116ddeeec14Snorby if_event_name(event), if_state_name(old_state)); 117ddeeec14Snorby return (0); 118ddeeec14Snorby } 119ddeeec14Snorby 120ddeeec14Snorby switch (iface_fsm[i].action) { 121ddeeec14Snorby case IF_ACT_STRT: 122ddeeec14Snorby ret = if_act_start(iface); 123ddeeec14Snorby break; 124ddeeec14Snorby case IF_ACT_RST: 125ddeeec14Snorby ret = if_act_reset(iface); 126ddeeec14Snorby break; 127ddeeec14Snorby case IF_ACT_NOTHING: 128ddeeec14Snorby /* do nothing */ 129ddeeec14Snorby break; 130ddeeec14Snorby } 131ddeeec14Snorby 132ddeeec14Snorby if (ret) { 133ddeeec14Snorby log_debug("if_fsm: error changing state for interface %s, " 134ddeeec14Snorby "event '%s', state '%s'", iface->name, if_event_name(event), 135ddeeec14Snorby if_state_name(old_state)); 136ddeeec14Snorby return (0); 137ddeeec14Snorby } 138ddeeec14Snorby 139ddeeec14Snorby if (new_state != 0) 140ddeeec14Snorby iface->state = new_state; 141ddeeec14Snorby 1424d8b14b6Smichele if (old_state == IF_STA_ACTIVE && iface->state == IF_STA_DOWN) 1434d8b14b6Smichele ripe_demote_iface(iface, 0); 1444d8b14b6Smichele if (old_state & IF_STA_DOWN && iface->state == IF_STA_ACTIVE) 1454d8b14b6Smichele ripe_demote_iface(iface, 1); 1464d8b14b6Smichele 147ddeeec14Snorby log_debug("if_fsm: event '%s' resulted in action '%s' and changing " 148ddeeec14Snorby "state for interface %s from '%s' to '%s'", 149ddeeec14Snorby if_event_name(event), if_action_name(iface_fsm[i].action), 150ddeeec14Snorby iface->name, if_state_name(old_state), if_state_name(iface->state)); 151ddeeec14Snorby 152ddeeec14Snorby return (ret); 153ddeeec14Snorby } 154ddeeec14Snorby 155ddeeec14Snorby struct iface * 156ddeeec14Snorby if_find_index(u_short ifindex) 157ddeeec14Snorby { 158ddeeec14Snorby struct iface *iface; 159ddeeec14Snorby 160ddeeec14Snorby LIST_FOREACH(iface, &conf->iface_list, entry) { 161ddeeec14Snorby if (iface->ifindex == ifindex) 162ddeeec14Snorby return (iface); 163ddeeec14Snorby } 164ddeeec14Snorby 165ddeeec14Snorby return (NULL); 166ddeeec14Snorby } 167ddeeec14Snorby 168ddeeec14Snorby 169ddeeec14Snorby /* actions */ 170ddeeec14Snorby int 171ddeeec14Snorby if_act_start(struct iface *iface) 172ddeeec14Snorby { 173ddeeec14Snorby struct in_addr addr; 174ddeeec14Snorby struct timeval now; 175ddeeec14Snorby 176ddeeec14Snorby if (iface->passive) { 177ddeeec14Snorby log_debug("if_act_start: cannot start passive interface %s", 178ddeeec14Snorby iface->name); 179ddeeec14Snorby return (0); 180ddeeec14Snorby } 181ddeeec14Snorby 182ddeeec14Snorby if (!((iface->flags & IFF_UP) && 1839a2e0324Sclaudio LINK_STATE_IS_UP(iface->linkstate))) { 184ddeeec14Snorby log_debug("if_act_start: interface %s link down", 185ddeeec14Snorby iface->name); 186ddeeec14Snorby return (0); 187ddeeec14Snorby } 188ddeeec14Snorby 189ddeeec14Snorby gettimeofday(&now, NULL); 190ddeeec14Snorby iface->uptime = now.tv_sec; 191ddeeec14Snorby 192ddeeec14Snorby switch (iface->type) { 193ddeeec14Snorby case IF_TYPE_POINTOPOINT: 194ddeeec14Snorby case IF_TYPE_BROADCAST: 195*28b8bcf0Sflorian inet_pton(AF_INET, ALL_RIP_ROUTERS, &addr); 196ddeeec14Snorby if (if_join_group(iface, &addr)) { 197ddeeec14Snorby log_warn("if_act_start: error joining group %s, " 198ddeeec14Snorby "interface %s", inet_ntoa(addr), iface->name); 199ddeeec14Snorby return (-1); 200ddeeec14Snorby } 201ddeeec14Snorby 202ddeeec14Snorby iface->state = IF_STA_ACTIVE; 203ddeeec14Snorby break; 204ddeeec14Snorby default: 205ddeeec14Snorby fatalx("if_act_start: unknown interface type"); 206ddeeec14Snorby } 207ddeeec14Snorby 208ddeeec14Snorby return (0); 209ddeeec14Snorby } 210ddeeec14Snorby 211ddeeec14Snorby int 212ddeeec14Snorby if_act_reset(struct iface *iface) 213ddeeec14Snorby { 214ddeeec14Snorby struct nbr *nbr = NULL; 215ddeeec14Snorby struct in_addr addr; 216ddeeec14Snorby 217ddeeec14Snorby if (iface->passive) 218ddeeec14Snorby return (0); 219ddeeec14Snorby 220ddeeec14Snorby switch (iface->type) { 221ddeeec14Snorby case IF_TYPE_POINTOPOINT: 222ddeeec14Snorby case IF_TYPE_BROADCAST: 223*28b8bcf0Sflorian inet_pton(AF_INET, ALL_RIP_ROUTERS, &addr); 224ddeeec14Snorby if (if_leave_group(iface, &addr)) { 225ddeeec14Snorby log_warn("if_act_reset: error leaving group %s, " 226ddeeec14Snorby "interface %s", inet_ntoa(addr), iface->name); 227ddeeec14Snorby } 228ddeeec14Snorby break; 229ddeeec14Snorby default: 230ddeeec14Snorby fatalx("if_act_reset: unknown interface type"); 231ddeeec14Snorby } 232ddeeec14Snorby 233ddeeec14Snorby LIST_FOREACH(nbr, &iface->nbr_list, entry) { 234ddeeec14Snorby if (nbr_fsm(nbr, NBR_EVT_KILL_NBR)) { 235ddeeec14Snorby log_debug("if_act_reset: error killing neighbor %s", 236ddeeec14Snorby inet_ntoa(nbr->id)); 237ddeeec14Snorby } 238ddeeec14Snorby } 239ddeeec14Snorby 240ddeeec14Snorby return (0); 241ddeeec14Snorby } 242ddeeec14Snorby 243ddeeec14Snorby const char * 244ddeeec14Snorby if_event_name(int event) 245ddeeec14Snorby { 246ddeeec14Snorby return (if_event_names[event]); 247ddeeec14Snorby } 248ddeeec14Snorby 249ddeeec14Snorby const char * 250ddeeec14Snorby if_action_name(int action) 251ddeeec14Snorby { 252ddeeec14Snorby return (if_action_names[action]); 253ddeeec14Snorby } 254ddeeec14Snorby 255ddeeec14Snorby /* misc */ 256ddeeec14Snorby int 257ddeeec14Snorby if_set_mcast_ttl(int fd, u_int8_t ttl) 258ddeeec14Snorby { 259ddeeec14Snorby if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, 260df69c215Sderaadt (char *)&ttl, sizeof(ttl)) == -1) { 261ddeeec14Snorby log_warn("if_set_mcast_ttl: error setting " 262ddeeec14Snorby "IP_MULTICAST_TTL to %d", ttl); 263ddeeec14Snorby return (-1); 264ddeeec14Snorby } 265ddeeec14Snorby 266ddeeec14Snorby return (0); 267ddeeec14Snorby } 268ddeeec14Snorby 269ddeeec14Snorby int 270ddeeec14Snorby if_set_opt(int fd) 271ddeeec14Snorby { 272ddeeec14Snorby int yes = 1; 273ddeeec14Snorby 274ddeeec14Snorby if (setsockopt(fd, IPPROTO_IP, IP_RECVIF, &yes, 275df69c215Sderaadt sizeof(int)) == -1) { 276ddeeec14Snorby log_warn("if_set_opt: error setting IP_RECVIF"); 277ddeeec14Snorby return (-1); 278ddeeec14Snorby } 279ddeeec14Snorby 280ddeeec14Snorby return (0); 281ddeeec14Snorby } 282ddeeec14Snorby 283ddeeec14Snorby int 284ddeeec14Snorby if_set_tos(int fd, int tos) 285ddeeec14Snorby { 286ddeeec14Snorby if (setsockopt(fd, IPPROTO_IP, IP_TOS, 287df69c215Sderaadt (int *)&tos, sizeof(tos)) == -1) { 288ddeeec14Snorby log_warn("if_set_tos: error setting IP_TOS to 0x%x", tos); 289ddeeec14Snorby return (-1); 290ddeeec14Snorby } 291ddeeec14Snorby 292ddeeec14Snorby return (0); 293ddeeec14Snorby } 294ddeeec14Snorby 295ddeeec14Snorby int 296ddeeec14Snorby if_set_mcast(struct iface *iface) 297ddeeec14Snorby { 298ddeeec14Snorby switch (iface->type) { 299ddeeec14Snorby case IF_TYPE_POINTOPOINT: 300ddeeec14Snorby case IF_TYPE_BROADCAST: 301ddeeec14Snorby if (setsockopt(iface->fd, IPPROTO_IP, IP_MULTICAST_IF, 302df69c215Sderaadt &iface->addr.s_addr, sizeof(iface->addr.s_addr)) == -1) { 303ddeeec14Snorby log_debug("if_set_mcast: error setting " 304ddeeec14Snorby "IP_MULTICAST_IF, interface %s", iface->name); 305ddeeec14Snorby return (-1); 306ddeeec14Snorby } 307ddeeec14Snorby break; 308ddeeec14Snorby default: 309ddeeec14Snorby fatalx("if_set_mcast: unknown interface type"); 310ddeeec14Snorby } 311ddeeec14Snorby 312ddeeec14Snorby return (0); 313ddeeec14Snorby } 314ddeeec14Snorby 315ddeeec14Snorby int 316ddeeec14Snorby if_set_mcast_loop(int fd) 317ddeeec14Snorby { 318ddeeec14Snorby u_int8_t loop = 0; 319ddeeec14Snorby 320ddeeec14Snorby if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, 321df69c215Sderaadt (char *)&loop, sizeof(loop)) == -1) { 322ddeeec14Snorby log_warn("if_set_mcast_loop: error setting IP_MULTICAST_LOOP"); 323ddeeec14Snorby return (-1); 324ddeeec14Snorby } 325ddeeec14Snorby 326ddeeec14Snorby return (0); 327ddeeec14Snorby } 328ddeeec14Snorby 329ddeeec14Snorby void 330ddeeec14Snorby if_set_recvbuf(int fd) 331ddeeec14Snorby { 332ddeeec14Snorby int bsize; 333ddeeec14Snorby 334ddeeec14Snorby bsize = 65535; 335ddeeec14Snorby while (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bsize, 336ddeeec14Snorby sizeof(bsize)) == -1) 337ddeeec14Snorby bsize /= 2; 338ddeeec14Snorby } 339ddeeec14Snorby 340ddeeec14Snorby int 341ddeeec14Snorby if_join_group(struct iface *iface, struct in_addr *addr) 342ddeeec14Snorby { 343ddeeec14Snorby struct ip_mreq mreq; 344ddeeec14Snorby 345ddeeec14Snorby switch (iface->type) { 346ddeeec14Snorby case IF_TYPE_POINTOPOINT: 347ddeeec14Snorby case IF_TYPE_BROADCAST: 348ddeeec14Snorby mreq.imr_multiaddr.s_addr = addr->s_addr; 349ddeeec14Snorby mreq.imr_interface.s_addr = iface->addr.s_addr; 350ddeeec14Snorby 351ddeeec14Snorby if (setsockopt(iface->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 352df69c215Sderaadt (void *)&mreq, sizeof(mreq)) == -1) 353ddeeec14Snorby return (-1); 354ddeeec14Snorby break; 355ddeeec14Snorby default: 356ddeeec14Snorby fatalx("if_join_group: unknown interface type"); 357ddeeec14Snorby } 358ddeeec14Snorby 359ddeeec14Snorby return (0); 360ddeeec14Snorby } 361ddeeec14Snorby 362ddeeec14Snorby int 363ddeeec14Snorby if_leave_group(struct iface *iface, struct in_addr *addr) 364ddeeec14Snorby { 365ddeeec14Snorby struct ip_mreq mreq; 366ddeeec14Snorby 367ddeeec14Snorby switch (iface->type) { 368ddeeec14Snorby case IF_TYPE_POINTOPOINT: 369ddeeec14Snorby case IF_TYPE_BROADCAST: 370ddeeec14Snorby mreq.imr_multiaddr.s_addr = addr->s_addr; 371ddeeec14Snorby mreq.imr_interface.s_addr = iface->addr.s_addr; 372ddeeec14Snorby 373ddeeec14Snorby if (setsockopt(iface->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, 374df69c215Sderaadt (void *)&mreq, sizeof(mreq)) == -1) 375ddeeec14Snorby return (-1); 376ddeeec14Snorby break; 377ddeeec14Snorby default: 378ddeeec14Snorby fatalx("if_leave_group: unknown interface type"); 379ddeeec14Snorby } 380ddeeec14Snorby 381ddeeec14Snorby return (0); 382ddeeec14Snorby } 383ddeeec14Snorby 384ddeeec14Snorby struct iface * 385ddeeec14Snorby if_new(struct kif *kif) 386ddeeec14Snorby { 387ddeeec14Snorby struct sockaddr_in *sain; 388ddeeec14Snorby struct iface *iface; 389ddeeec14Snorby struct ifreq *ifr; 390ddeeec14Snorby int s; 391ddeeec14Snorby 392ddeeec14Snorby if ((iface = calloc(1, sizeof(*iface))) == NULL) 393ddeeec14Snorby err(1, "if_new: calloc"); 394ddeeec14Snorby 395ddeeec14Snorby iface->state = IF_STA_DOWN; 396ddeeec14Snorby 397ddeeec14Snorby LIST_INIT(&iface->nbr_list); 398ddeeec14Snorby TAILQ_INIT(&iface->rp_list); 399ddeeec14Snorby TAILQ_INIT(&iface->rq_list); 400ddeeec14Snorby 401ddeeec14Snorby strlcpy(iface->name, kif->ifname, sizeof(iface->name)); 402ddeeec14Snorby 403ddeeec14Snorby if ((ifr = calloc(1, sizeof(*ifr))) == NULL) 404ddeeec14Snorby err(1, "if_new: calloc"); 405ddeeec14Snorby 406ddeeec14Snorby /* set up ifreq */ 407ddeeec14Snorby strlcpy(ifr->ifr_name, kif->ifname, sizeof(ifr->ifr_name)); 40833229c10Sclaudio if ((s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 409df69c215Sderaadt 0)) == -1) 410ddeeec14Snorby err(1, "if_new: socket"); 411ddeeec14Snorby 412ddeeec14Snorby /* get type */ 413ddeeec14Snorby if (kif->flags & IFF_POINTOPOINT) 414ddeeec14Snorby iface->type = IF_TYPE_POINTOPOINT; 415ddeeec14Snorby if (kif->flags & IFF_BROADCAST && 416ddeeec14Snorby kif->flags & IFF_MULTICAST) 417ddeeec14Snorby iface->type = IF_TYPE_BROADCAST; 418ddeeec14Snorby if (kif->flags & IFF_LOOPBACK) { 419ddeeec14Snorby iface->type = IF_TYPE_POINTOPOINT; 420ddeeec14Snorby /* XXX protect loopback from sending packets over lo? */ 421ddeeec14Snorby } 422ddeeec14Snorby 423ddeeec14Snorby /* get mtu, index and flags */ 424ddeeec14Snorby iface->mtu = kif->mtu; 425ddeeec14Snorby iface->ifindex = kif->ifindex; 426ddeeec14Snorby iface->flags = kif->flags; 427ddeeec14Snorby iface->linkstate = kif->link_state; 42816530d00Sstsp iface->if_type = kif->if_type; 42990cb0607Sclaudio iface->baudrate = kif->baudrate; 430ddeeec14Snorby 431ddeeec14Snorby /* get address */ 432df69c215Sderaadt if (ioctl(s, SIOCGIFADDR, ifr) == -1) 433ddeeec14Snorby err(1, "if_new: cannot get address"); 434ddeeec14Snorby sain = (struct sockaddr_in *)&ifr->ifr_addr; 435ddeeec14Snorby iface->addr = sain->sin_addr; 436ddeeec14Snorby 437ddeeec14Snorby /* get mask */ 438df69c215Sderaadt if (ioctl(s, SIOCGIFNETMASK, ifr) == -1) 439ddeeec14Snorby err(1, "if_new: cannot get mask"); 440ddeeec14Snorby sain = (struct sockaddr_in *)&ifr->ifr_addr; 441ddeeec14Snorby iface->mask = sain->sin_addr; 442ddeeec14Snorby 443ddeeec14Snorby /* get p2p dst address */ 444ddeeec14Snorby if (kif->flags & IFF_POINTOPOINT) { 445df69c215Sderaadt if (ioctl(s, SIOCGIFDSTADDR, ifr) == -1) 446ddeeec14Snorby err(1, "if_new: cannot get dst addr"); 447ddeeec14Snorby sain = (struct sockaddr_in *)&ifr->ifr_addr; 448ddeeec14Snorby iface->dst = sain->sin_addr; 449ddeeec14Snorby } 450ddeeec14Snorby 451ddeeec14Snorby free(ifr); 452ddeeec14Snorby close(s); 453ddeeec14Snorby 454ddeeec14Snorby return (iface); 455ddeeec14Snorby } 456ddeeec14Snorby 457ddeeec14Snorby void 458ddeeec14Snorby if_del(struct iface *iface) 459ddeeec14Snorby { 460ddeeec14Snorby struct nbr *nbr; 461ddeeec14Snorby 462ddeeec14Snorby log_debug("if_del: interface %s", iface->name); 463ddeeec14Snorby 464ddeeec14Snorby /* clear lists etc */ 465ddeeec14Snorby while ((nbr = LIST_FIRST(&iface->nbr_list)) != NULL) 466b38873a2Sjca nbr_del(nbr); 467ddeeec14Snorby 468ddeeec14Snorby /* XXX rq_list, rp_list */ 469ddeeec14Snorby 470ddeeec14Snorby free(iface); 471ddeeec14Snorby } 472ddeeec14Snorby 473ddeeec14Snorby struct ctl_iface * 474ddeeec14Snorby if_to_ctl(struct iface *iface) 475ddeeec14Snorby { 476ddeeec14Snorby static struct ctl_iface ictl; 477ddeeec14Snorby struct timeval now; 478ddeeec14Snorby 479ddeeec14Snorby memcpy(ictl.name, iface->name, sizeof(ictl.name)); 480ddeeec14Snorby memcpy(&ictl.addr, &iface->addr, sizeof(ictl.addr)); 481ddeeec14Snorby memcpy(&ictl.mask, &iface->mask, sizeof(ictl.mask)); 482ddeeec14Snorby 483ddeeec14Snorby ictl.ifindex = iface->ifindex; 484ddeeec14Snorby ictl.state = iface->state; 485ddeeec14Snorby ictl.mtu = iface->mtu; 486ddeeec14Snorby 487ddeeec14Snorby ictl.baudrate = iface->baudrate; 488ddeeec14Snorby ictl.flags = iface->flags; 489ddeeec14Snorby ictl.metric = iface->cost; 490ddeeec14Snorby ictl.type = iface->type; 491ddeeec14Snorby ictl.linkstate = iface->linkstate; 492ddeeec14Snorby ictl.passive = iface->passive; 49316530d00Sstsp ictl.if_type = iface->if_type; 494ddeeec14Snorby 495ddeeec14Snorby gettimeofday(&now, NULL); 496ddeeec14Snorby 497ddeeec14Snorby if (iface->state != IF_STA_DOWN) { 498ddeeec14Snorby ictl.uptime = now.tv_sec - iface->uptime; 499ddeeec14Snorby } else 500ddeeec14Snorby ictl.uptime = 0; 501ddeeec14Snorby 502ddeeec14Snorby return (&ictl); 503ddeeec14Snorby } 504