From 3f045a08812525505e165deea99a79447b44506b Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Sat, 24 Mar 2012 08:35:20 -0700 Subject: isisd: add Google's changes to IS-IS --- isisd/isis_pfpacket.c | 91 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 37 deletions(-) (limited to 'isisd/isis_pfpacket.c') diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 9e4165e3..42947b22 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -134,7 +134,7 @@ open_packet_socket (struct isis_circuit *circuit) circuit->fd = fd; - if (circuit->circ_type == CIRCUIT_T_BROADCAST) + if (if_is_broadcast (circuit->interface)) { /* * Join to multicast groups @@ -142,24 +142,22 @@ open_packet_socket (struct isis_circuit *circuit) * 8.4.2 - Broadcast subnetwork IIH PDUs * FIXME: is there a case only one will fail?? */ - if (circuit->circuit_is_type & IS_LEVEL_1) - { - /* joining ALL_L1_ISS */ - retval = isis_multicast_join (circuit->fd, 1, - circuit->interface->ifindex); - /* joining ALL_ISS */ - retval = isis_multicast_join (circuit->fd, 3, - circuit->interface->ifindex); - } - if (circuit->circuit_is_type & IS_LEVEL_2) - /* joining ALL_L2_ISS */ - retval = isis_multicast_join (circuit->fd, 2, - circuit->interface->ifindex); + if (circuit->is_type & IS_LEVEL_1) + /* joining ALL_L1_ISS */ + retval = isis_multicast_join (circuit->fd, 1, + circuit->interface->ifindex); + if (circuit->is_type & IS_LEVEL_2) + /* 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); + isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex); } return retval; @@ -184,12 +182,13 @@ isis_sock_init (struct isis_circuit *circuit) goto end; } - if (circuit->circ_type == CIRCUIT_T_BROADCAST) + /* 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 (circuit->circ_type == CIRCUIT_T_P2P) + else if (if_is_pointopoint (circuit->interface)) { circuit->tx = isis_send_pdu_p2p; circuit->rx = isis_recv_pdu_p2p; @@ -234,13 +233,14 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) if (bytesread < 0) { - zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s", - circuit->fd, safe_strerror (errno)); - zlog_warn ("circuit is %s", circuit->interface->name); - zlog_warn ("circuit fd %d", circuit->fd); - zlog_warn ("bytesread %d", bytesread); + zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, bytesread %d, " + "recvfrom(): %s", + circuit->interface->name, circuit->fd, bytesread, + safe_strerror (errno)); /* get rid of the packet */ - bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); + bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), + MSG_DONTWAIT, (struct sockaddr *) &s_addr, + (socklen_t *) &addr_len); return ISIS_WARNING; } /* @@ -249,15 +249,22 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING) { /* Read the packet into discard buff */ - bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); + bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), + MSG_DONTWAIT, (struct sockaddr *) &s_addr, + (socklen_t *) &addr_len); if (bytesread < 0) - zlog_warn ("isis_recv_pdu_bcast(): read() failed"); + zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed"); return ISIS_WARNING; } /* on lan we have to read to the static buff first */ - bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0, + bytesread = recvfrom (circuit->fd, sock_buff, sizeof (sock_buff), MSG_DONTWAIT, (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); + if (bytesread < 0) + { + zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed"); + return ISIS_WARNING; + } /* then we lose the LLC */ stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN); @@ -285,9 +292,11 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) if (s_addr.sll_pkttype == PACKET_OUTGOING) { /* Read the packet into discard buff */ - bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); + bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), + MSG_DONTWAIT, (struct sockaddr *) &s_addr, + (socklen_t *) &addr_len); if (bytesread < 0) - zlog_warn ("isis_recv_pdu_p2p(): read() failed"); + zlog_warn ("isis_recv_pdu_p2p(): recvfrom() failed"); return ISIS_WARNING; } @@ -309,6 +318,9 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) int isis_send_pdu_bcast (struct isis_circuit *circuit, int level) { + struct msghdr msg; + struct iovec iov[2]; + /* we need to do the LLC in here because of P2P circuits, which will * not need it */ @@ -321,7 +333,10 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level) sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN); sa.sll_ifindex = circuit->interface->ifindex; sa.sll_halen = ETH_ALEN; - if (level == 1) + /* RFC5309 section 4.1 recommends ALL_ISS */ + if (circuit->circ_type == CIRCUIT_T_P2P) + memcpy (&sa.sll_addr, ALL_ISS, ETH_ALEN); + else if (level == 1) memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); else memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); @@ -332,14 +347,17 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level) sock_buff[1] = 0xFE; sock_buff[2] = 0x03; - /* then we copy the data */ - memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data, - stream_get_endp (circuit->snd_stream)); + memset (&msg, 0, sizeof (msg)); + msg.msg_name = &sa; + msg.msg_namelen = sizeof (struct sockaddr_ll); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + iov[0].iov_base = sock_buff; + iov[0].iov_len = LLC_LEN; + iov[1].iov_base = circuit->snd_stream->data; + iov[1].iov_len = stream_get_endp (circuit->snd_stream); - /* now we can send this */ - written = sendto (circuit->fd, sock_buff, - stream_get_endp(circuit->snd_stream) + LLC_LEN, 0, - (struct sockaddr *) &sa, sizeof (struct sockaddr_ll)); + written = sendmsg (circuit->fd, &msg, 0); return ISIS_OK; } @@ -347,7 +365,6 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level) int isis_send_pdu_p2p (struct isis_circuit *circuit, int level) { - int written = 1; struct sockaddr_ll sa; -- cgit v1.2.1