static int open_packet_socket (struct isis_circuit *circuit) { struct sockaddr_ll s_addr; int fd, retval = ISIS_OK; fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL)); if (fd < 0) { zlog_warn ("open_packet_socket(): socket() failed %s", safe_strerror (errno)); return ISIS_WARNING; } /* * Bind to the physical interface */ memset (&s_addr, 0, sizeof (struct sockaddr_ll)); s_addr.sll_family = AF_PACKET; s_addr.sll_protocol = htons (ETH_P_ALL); s_addr.sll_ifindex = circuit->interface->ifindex; if (bind (fd, (struct sockaddr *) (&s_addr), sizeof (struct sockaddr_ll)) < 0) { zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno)); close (fd); return ISIS_WARNING; } circuit->fd = fd; if (if_is_broadcast (circuit->interface)) { /* * Join to multicast groups * according to * 8.4.2 - Broadcast subnetwork IIH PDUs * FIXME: is there a case only one will fail?? */ /* joining ALL_L1_ISS */ retval |= isis_multicast_join (circuit->fd, 1, circuit->interface->ifindex); /* joining ALL_L2_ISS */ retval |= isis_multicast_join (circuit->fd, 2, circuit->interface->ifindex); /* joining ALL_ISS (used in RFC 5309 p2p-over-lan as well) */ retval |= isis_multicast_join (circuit->fd, 3, circuit->interface->ifindex); } else { retval = isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex); } return retval; }
/* Set up interface's address, netmask (and broadcast? ). Solaris uses ifname:number semantics to set IP address aliases. */ int if_set_prefix(struct interface *ifp, struct connected *ifc) { int ret; struct ifreq ifreq; struct sockaddr_in addr; struct sockaddr_in broad; struct sockaddr_in mask; struct prefix_ipv4 ifaddr; struct prefix_ipv4 *p; p = (struct prefix_ipv4 *)ifc->address; ifaddr = *p; strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); addr.sin_addr = p->prefix; addr.sin_family = p->family; memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); if (ret < 0) return ret; /* We need mask for make broadcast addr. */ masklen2ip(p->prefixlen, &mask.sin_addr); if (if_is_broadcast(ifp)) { apply_mask_ipv4(&ifaddr); addr.sin_addr = ifaddr.prefix; broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); broad.sin_family = p->family; memcpy(&ifreq.ifr_broadaddr, &broad, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); if (ret < 0) return ret; } mask.sin_family = p->family; #ifdef SUNOS_5 memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS_5 */ ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); return ((ret < 0) ? ret : 0); }
/* Send RIP request packet to specified interface. */ static void rip_request_interface_send (struct interface *ifp, u_char version) { struct sockaddr_in to; /* RIPv2 support multicast. */ if (version == RIPv2 && if_is_multicast (ifp)) { if (IS_RIP_DEBUG_EVENT) zlog_debug ("multicast request on %s", ifp->name); rip_request_send (NULL, ifp, version, NULL); return; } /* RIPv1 and non multicast interface. */ if (if_is_pointopoint (ifp) || if_is_broadcast (ifp)) { struct listnode *cnode, *cnnode; struct connected *connected; if (IS_RIP_DEBUG_EVENT) zlog_debug ("broadcast request to %s", ifp->name); for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, connected)) { if (connected->address->family == AF_INET) { memset (&to, 0, sizeof (struct sockaddr_in)); to.sin_port = htons (RIP_PORT_DEFAULT); if (connected->destination) /* use specified broadcast or peer destination addr */ to.sin_addr = connected->destination->u.prefix4; else if (connected->address->prefixlen < IPV4_MAX_PREFIXLEN) /* calculate the appropriate broadcast address */ to.sin_addr.s_addr = ipv4_broadcast_addr(connected->address->u.prefix4.s_addr, connected->address->prefixlen); else /* do not know where to send the packet */ continue; if (IS_RIP_DEBUG_EVENT) zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr)); rip_request_send (&to, ifp, version, connected); } } } }
/* Interface address modification. */ int netlink_address (int cmd, int family, struct interface *ifp, struct connected *ifc) { int bytelen; struct prefix *p; struct { struct nlmsghdr n; struct ifaddrmsg ifa; char buf[1024]; } req; p = ifc->address; memset (&req, 0, sizeof req); bytelen = (family == AF_INET ? 4 : 16); req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.ifa.ifa_family = family; req.ifa.ifa_index = ifp->ifindex; req.ifa.ifa_prefixlen = p->prefixlen; addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); if (family == AF_INET && cmd == RTM_NEWADDR) { if (if_is_broadcast (ifp) && ifc->destination) { p = ifc->destination; addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen); } } if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY); if (ifc->label) addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, strlen (ifc->label) + 1); return netlink_talk (&req.n, &netlink_cmd); }
/* * Create the socket and set the tx/rx funcs */ int isis_sock_init (struct isis_circuit *circuit) { int retval = ISIS_OK; if (isisd_privs.change (ZPRIVS_RAISE)) zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno)); retval = open_packet_socket (circuit); if (retval != ISIS_OK) { zlog_warn ("%s: could not initialize the socket", __func__); goto end; } /* Assign Rx and Tx callbacks are based on real if type */ if (if_is_broadcast (circuit->interface)) { circuit->tx = isis_send_pdu_bcast; circuit->rx = isis_recv_pdu_bcast; } else if (if_is_pointopoint (circuit->interface)) { circuit->tx = isis_send_pdu_p2p; circuit->rx = isis_recv_pdu_p2p; } else { zlog_warn ("isis_sock_init(): unknown circuit type"); retval = ISIS_WARNING; goto end; } end: if (isisd_privs.change (ZPRIVS_LOWER)) zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno)); return retval; }
/* show specified interface structure */ static int ospf6_interface_show (struct vty *vty, struct interface *ifp) { struct ospf6_interface *oi; struct connected *c; struct prefix *p; struct listnode *i; char strbuf[64], drouter[32], bdrouter[32]; const char *updown[3] = {"down", "up", NULL}; const char *type; struct timeval res, now; char duration[32]; struct ospf6_lsa *lsa; /* check physical interface type */ if (if_is_loopback (ifp)) type = "LOOPBACK"; else if (if_is_broadcast (ifp)) type = "BROADCAST"; else if (if_is_pointopoint (ifp)) type = "POINTOPOINT"; else type = "UNKNOWN"; vty_out (vty, "%s is %s, type %s%s", ifp->name, updown[if_is_up (ifp)], type, VNL); vty_out (vty, " Interface ID: %d%s", ifp->ifindex, VNL); if (ifp->info == NULL) { vty_out (vty, " OSPF not enabled on this interface%s", VNL); return 0; } else oi = (struct ospf6_interface *) ifp->info; vty_out (vty, " Internet Address:%s", VNL); for (ALL_LIST_ELEMENTS_RO (ifp->connected, i, c)) { p = c->address; prefix2str (p, strbuf, sizeof (strbuf)); switch (p->family) { case AF_INET: vty_out (vty, " inet : %s%s", strbuf, VNL); break; case AF_INET6: vty_out (vty, " inet6: %s%s", strbuf, VNL); break; default: vty_out (vty, " ??? : %s%s", strbuf, VNL); break; } } if (oi->area) { vty_out (vty, " Instance ID %d, Interface MTU %d (autodetect: %d)%s", oi->instance_id, oi->ifmtu, ifp->mtu6, VNL); vty_out (vty, " MTU mismatch detection: %s%s", oi->mtu_ignore ? "disabled" : "enabled", VNL); inet_ntop (AF_INET, &oi->area->area_id, strbuf, sizeof (strbuf)); vty_out (vty, " Area ID %s, Cost %hu%s", strbuf, oi->cost, VNL); } else vty_out (vty, " Not Attached to Area%s", VNL); vty_out (vty, " State %s, Transmit Delay %d sec, Priority %d%s", ospf6_interface_state_str[oi->state], oi->transdelay, oi->priority, VNL); vty_out (vty, " Timer intervals configured:%s", VNL); vty_out (vty, " Hello %d, Dead %d, Retransmit %d%s", oi->hello_interval, oi->dead_interval, oi->rxmt_interval, VNL); inet_ntop (AF_INET, &oi->drouter, drouter, sizeof (drouter)); inet_ntop (AF_INET, &oi->bdrouter, bdrouter, sizeof (bdrouter)); vty_out (vty, " DR: %s BDR: %s%s", drouter, bdrouter, VNL); vty_out (vty, " Number of I/F scoped LSAs is %u%s", oi->lsdb->count, VNL); bane_gettime (BANE_CLK_MONOTONIC, &now); timerclear (&res); if (oi->thread_send_lsupdate) timersub (&oi->thread_send_lsupdate->u.sands, &now, &res); timerstring (&res, duration, sizeof (duration)); vty_out (vty, " %d Pending LSAs for LSUpdate in Time %s [thread %s]%s", oi->lsupdate_list->count, duration, (oi->thread_send_lsupdate ? "on" : "off"), VNL); for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa; lsa = ospf6_lsdb_next (lsa)) vty_out (vty, " %s%s", lsa->name, VNL); timerclear (&res); if (oi->thread_send_lsack) timersub (&oi->thread_send_lsack->u.sands, &now, &res); timerstring (&res, duration, sizeof (duration)); vty_out (vty, " %d Pending LSAs for LSAck in Time %s [thread %s]%s", oi->lsack_list->count, duration, (oi->thread_send_lsack ? "on" : "off"), VNL); for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa; lsa = ospf6_lsdb_next (lsa)) vty_out (vty, " %s%s", lsa->name, VNL); return 0; }