diff options
Diffstat (limited to 'isisd/isis_pfpacket.c')
| -rw-r--r-- | isisd/isis_pfpacket.c | 685 | 
1 files changed, 332 insertions, 353 deletions
diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index c5985dcd8d..e24901b0de 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -2,17 +2,17 @@   * IS-IS Rout(e)ing protocol - isis_pfpacket.c   *   * Copyright (C) 2001,2002    Sampo Saaristo - *                            Tampere University of Technology       + *                            Tampere University of Technology   *                            Institute of Communications Engineering   * - * This program is free software; you can redistribute it and/or modify it  - * under the terms of the GNU General Public Licenseas published by the Free  - * Software Foundation; either version 2 of the License, or (at your option)  + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option)   * any later version.   * - * This program is distributed in the hope that it will be useful,but WITHOUT  - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   * more details.   *   * You should have received a copy of the GNU General Public License along @@ -22,7 +22,7 @@  #include <zebra.h>  #if ISIS_METHOD == ISIS_METHOD_PFPACKET -#include <net/ethernet.h>	/* the L2 protocols */ +#include <net/ethernet.h> /* the L2 protocols */  #include <netpacket/packet.h>  #include <linux/filter.h> @@ -47,17 +47,17 @@  extern struct zebra_privs_t isisd_privs;  /* tcpdump -i eth0 'isis' -dd */ -static struct sock_filter isisfilter[] = { -/* NB: we're in SOCK_DGRAM, so src/dst mac + length are stripped off! - * (OTOH it's a bit more lower-layer agnostic and might work over GRE?) */ -/*	{ 0x28, 0, 0, 0x0000000c - 14 }, */ -/*	{ 0x25, 5, 0, 0x000005dc }, */ -	{ 0x28, 0, 0, 0x0000000e - 14 }, -	{ 0x15, 0, 3, 0x0000fefe }, -	{ 0x30, 0, 0, 0x00000011 - 14 }, -	{ 0x15, 0, 1, 0x00000083 }, -	{ 0x6, 0, 0, 0x00040000 }, -	{ 0x6, 0, 0, 0x00000000 }, +static struct sock_filter isisfilter[] = +	{ +		/* NB: we're in SOCK_DGRAM, so src/dst mac + length are stripped +		 * off! +		 * (OTOH it's a bit more lower-layer agnostic and might work +		 * over GRE?) */ +		/*	{ 0x28, 0, 0, 0x0000000c - 14 }, */ +		/*	{ 0x25, 5, 0, 0x000005dc }, */ +		{0x28, 0, 0, 0x0000000e - 14}, {0x15, 0, 3, 0x0000fefe}, +		{0x30, 0, 0, 0x00000011 - 14}, {0x15, 0, 1, 0x00000083}, +		{0x6, 0, 0, 0x00040000},       {0x6, 0, 0, 0x00000000},  };  static struct sock_fprog bpf = { @@ -70,10 +70,10 @@ static struct sock_fprog bpf = {   * ISO 10589 - 8.4.8   */ -u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; -u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; -u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; -u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; +u_char ALL_L1_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x14}; +u_char ALL_L2_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x15}; +u_char ALL_ISS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05}; +u_char ALL_ESS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04};  static uint8_t discard_buff[8192];  static uint8_t sock_buff[8192]; @@ -82,367 +82,346 @@ static uint8_t sock_buff[8192];   * if level is 0 we are joining p2p multicast   * FIXME: and the p2p multicast being ???   */ -static int -isis_multicast_join (int fd, int registerto, int if_num) +static int isis_multicast_join(int fd, int registerto, int if_num)  { -  struct packet_mreq mreq; - -  memset (&mreq, 0, sizeof (mreq)); -  mreq.mr_ifindex = if_num; -  if (registerto) -    { -      mreq.mr_type = PACKET_MR_MULTICAST; -      mreq.mr_alen = ETH_ALEN; -      if (registerto == 1) -	memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN); -      else if (registerto == 2) -	memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN); -      else if (registerto == 3) -	memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN); -      else -	memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN); - -    } -  else -    { -      mreq.mr_type = PACKET_MR_ALLMULTI; -    } +	struct packet_mreq mreq; + +	memset(&mreq, 0, sizeof(mreq)); +	mreq.mr_ifindex = if_num; +	if (registerto) { +		mreq.mr_type = PACKET_MR_MULTICAST; +		mreq.mr_alen = ETH_ALEN; +		if (registerto == 1) +			memcpy(&mreq.mr_address, ALL_L1_ISS, ETH_ALEN); +		else if (registerto == 2) +			memcpy(&mreq.mr_address, ALL_L2_ISS, ETH_ALEN); +		else if (registerto == 3) +			memcpy(&mreq.mr_address, ALL_ISS, ETH_ALEN); +		else +			memcpy(&mreq.mr_address, ALL_ESS, ETH_ALEN); + +	} else { +		mreq.mr_type = PACKET_MR_ALLMULTI; +	}  #ifdef EXTREME_DEBUG -  zlog_debug ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, " -	      "address = %02x:%02x:%02x:%02x:%02x:%02x", -	      fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1], -	      mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4], -	      mreq.mr_address[5]); +	zlog_debug( +		"isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, " +		"address = %02x:%02x:%02x:%02x:%02x:%02x", +		fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1], +		mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4], +		mreq.mr_address[5]);  #endif /* EXTREME_DEBUG */ -  if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, -		  sizeof (struct packet_mreq))) -    { -      zlog_warn ("isis_multicast_join(): setsockopt(): %s", safe_strerror (errno)); -      return ISIS_WARNING; -    } - -  return ISIS_OK; +	if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, +		       sizeof(struct packet_mreq))) { +		zlog_warn("isis_multicast_join(): setsockopt(): %s", +			  safe_strerror(errno)); +		return ISIS_WARNING; +	} + +	return ISIS_OK;  } -static int -open_packet_socket (struct isis_circuit *circuit) +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; -    } - -  if (setsockopt (fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof (bpf))) -    { -      zlog_warn ("open_packet_socket(): SO_ATTACH_FILTER failed: %s", -		 safe_strerror (errno)); -    } - -  /* -   * 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; +	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; +	} + +	if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))) { +		zlog_warn("open_packet_socket(): SO_ATTACH_FILTER failed: %s", +			  safe_strerror(errno)); +	} + +	/* +	 * 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;  }  /*   * Create the socket and set the tx/rx funcs   */ -int -isis_sock_init (struct isis_circuit *circuit) +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; -    } +	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)); +	if (isisd_privs.change(ZPRIVS_LOWER)) +		zlog_err("%s: could not lower privs, %s", __func__, +			 safe_strerror(errno)); -  return retval; +	return retval;  } -static inline int -llc_check (u_char * llc) +static inline int llc_check(u_char *llc)  { -  if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3) -    return 0; +	if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3) +		return 0; -  return 1; +	return 1;  } -int -isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) +int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa)  { -  int bytesread, addr_len; -  struct sockaddr_ll s_addr; -  u_char llc[LLC_LEN]; - -  addr_len = sizeof (s_addr); - -  memset (&s_addr, 0, sizeof (struct sockaddr_ll)); - -  bytesread = recvfrom (circuit->fd, (void *) &llc, -			LLC_LEN, MSG_PEEK, -			(struct sockaddr *) &s_addr, (socklen_t *) &addr_len); - -  if ((bytesread < 0) || (s_addr.sll_ifindex != (int)circuit->interface->ifindex)) -    { -      if (bytesread < 0) -        { -          zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, " -                     "bytesread %d, recvfrom(): %s", -                     circuit->interface->name, circuit->fd, bytesread, -                     safe_strerror (errno)); -        } -      if (s_addr.sll_ifindex != (int)circuit->interface->ifindex) -        { -          zlog_warn("packet is received on multiple interfaces: " -                    "socket interface %d, circuit interface %d, " -                    "packet type %u", -                    s_addr.sll_ifindex, circuit->interface->ifindex, -                    s_addr.sll_pkttype); -        } - -      /* get rid of the packet */ -      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(): recvfrom() failed"); - -      return ISIS_WARNING; -    } -  /* -   * Filtering by llc field, discard packets sent by this host (other circuit) -   */ -  if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING) -    { -      /*  Read the packet into 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(): recvfrom() failed"); -      return ISIS_WARNING; -    } - -  /* on lan we have to read to the static buff first */ -  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); - -  memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); - -  return ISIS_OK; +	int bytesread, addr_len; +	struct sockaddr_ll s_addr; +	u_char llc[LLC_LEN]; + +	addr_len = sizeof(s_addr); + +	memset(&s_addr, 0, sizeof(struct sockaddr_ll)); + +	bytesread = +		recvfrom(circuit->fd, (void *)&llc, LLC_LEN, MSG_PEEK, +			 (struct sockaddr *)&s_addr, (socklen_t *)&addr_len); + +	if ((bytesread < 0) +	    || (s_addr.sll_ifindex != (int)circuit->interface->ifindex)) { +		if (bytesread < 0) { +			zlog_warn( +				"isis_recv_packet_bcast(): ifname %s, fd %d, " +				"bytesread %d, recvfrom(): %s", +				circuit->interface->name, circuit->fd, +				bytesread, safe_strerror(errno)); +		} +		if (s_addr.sll_ifindex != (int)circuit->interface->ifindex) { +			zlog_warn( +				"packet is received on multiple interfaces: " +				"socket interface %d, circuit interface %d, " +				"packet type %u", +				s_addr.sll_ifindex, circuit->interface->ifindex, +				s_addr.sll_pkttype); +		} + +		/* get rid of the packet */ +		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(): recvfrom() failed"); + +		return ISIS_WARNING; +	} +	/* +	 * Filtering by llc field, discard packets sent by this host (other +	 * circuit) +	 */ +	if (!llc_check(llc) || s_addr.sll_pkttype == PACKET_OUTGOING) { +		/*  Read the packet into 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(): recvfrom() failed"); +		return ISIS_WARNING; +	} + +	/* on lan we have to read to the static buff first */ +	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); + +	memcpy(ssnpa, &s_addr.sll_addr, s_addr.sll_halen); + +	return ISIS_OK;  } -int -isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) +int isis_recv_pdu_p2p(struct isis_circuit *circuit, u_char *ssnpa)  { -  int bytesread, addr_len; -  struct sockaddr_ll s_addr; - -  memset (&s_addr, 0, sizeof (struct sockaddr_ll)); -  addr_len = sizeof (s_addr); - -  /* we can read directly to the stream */ -  stream_recvfrom (circuit->rcv_stream, circuit->fd, -                   circuit->interface->mtu, 0, -                   (struct sockaddr *) &s_addr, -                   (socklen_t *) &addr_len); - -  if (s_addr.sll_pkttype == PACKET_OUTGOING) -    { -      /*  Read the packet into 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(): recvfrom() failed"); -      return ISIS_WARNING; -    } - -  /* If we don't have protocol type 0x00FE which is -   * ISO over GRE we exit with pain :) -   */ -  if (ntohs (s_addr.sll_protocol) != 0x00FE) -    { -      zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X", -		 ntohs (s_addr.sll_protocol)); -      return ISIS_WARNING; -    } - -  memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); - -  return ISIS_OK; +	int bytesread, addr_len; +	struct sockaddr_ll s_addr; + +	memset(&s_addr, 0, sizeof(struct sockaddr_ll)); +	addr_len = sizeof(s_addr); + +	/* we can read directly to the stream */ +	stream_recvfrom(circuit->rcv_stream, circuit->fd, +			circuit->interface->mtu, 0, (struct sockaddr *)&s_addr, +			(socklen_t *)&addr_len); + +	if (s_addr.sll_pkttype == PACKET_OUTGOING) { +		/*  Read the packet into 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(): recvfrom() failed"); +		return ISIS_WARNING; +	} + +	/* If we don't have protocol type 0x00FE which is +	 * ISO over GRE we exit with pain :) +	 */ +	if (ntohs(s_addr.sll_protocol) != 0x00FE) { +		zlog_warn("isis_recv_pdu_p2p(): protocol mismatch(): %X", +			  ntohs(s_addr.sll_protocol)); +		return ISIS_WARNING; +	} + +	memcpy(ssnpa, &s_addr.sll_addr, s_addr.sll_halen); + +	return ISIS_OK;  } -int -isis_send_pdu_bcast (struct isis_circuit *circuit, int level) +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 -   */ -  struct sockaddr_ll sa; - -  stream_set_getp (circuit->snd_stream, 0); -  memset (&sa, 0, sizeof (struct sockaddr_ll)); -  sa.sll_family = AF_PACKET; - -  size_t frame_size = stream_get_endp(circuit->snd_stream) + LLC_LEN; -  sa.sll_protocol = htons(isis_ethertype(frame_size)); -  sa.sll_ifindex = circuit->interface->ifindex; -  sa.sll_halen = ETH_ALEN; -  /* 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); - -  /* on a broadcast circuit */ -  /* first we put the LLC in */ -  sock_buff[0] = 0xFE; -  sock_buff[1] = 0xFE; -  sock_buff[2] = 0x03; - -  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); - -  if (sendmsg(circuit->fd, &msg, 0) < 0) -    { -      zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", -                circuit->interface->name, safe_strerror(errno)); -      if (ERRNO_IO_RETRY(errno)) -        return ISIS_WARNING; -      return ISIS_ERROR; -    } -  return ISIS_OK; +	struct msghdr msg; +	struct iovec iov[2]; + +	/* we need to do the LLC in here because of P2P circuits, which will +	 * not need it +	 */ +	struct sockaddr_ll sa; + +	stream_set_getp(circuit->snd_stream, 0); +	memset(&sa, 0, sizeof(struct sockaddr_ll)); +	sa.sll_family = AF_PACKET; + +	size_t frame_size = stream_get_endp(circuit->snd_stream) + LLC_LEN; +	sa.sll_protocol = htons(isis_ethertype(frame_size)); +	sa.sll_ifindex = circuit->interface->ifindex; +	sa.sll_halen = ETH_ALEN; +	/* 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); + +	/* on a broadcast circuit */ +	/* first we put the LLC in */ +	sock_buff[0] = 0xFE; +	sock_buff[1] = 0xFE; +	sock_buff[2] = 0x03; + +	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); + +	if (sendmsg(circuit->fd, &msg, 0) < 0) { +		zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", +			  circuit->interface->name, safe_strerror(errno)); +		if (ERRNO_IO_RETRY(errno)) +			return ISIS_WARNING; +		return ISIS_ERROR; +	} +	return ISIS_OK;  } -int -isis_send_pdu_p2p (struct isis_circuit *circuit, int level) +int isis_send_pdu_p2p(struct isis_circuit *circuit, int level)  { -  struct sockaddr_ll sa; -  ssize_t rv; - -  stream_set_getp (circuit->snd_stream, 0); -  memset (&sa, 0, sizeof (struct sockaddr_ll)); -  sa.sll_family = AF_PACKET; -  sa.sll_ifindex = circuit->interface->ifindex; -  sa.sll_halen = ETH_ALEN; -  if (level == 1) -    memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); -  else -    memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); - - -  /* lets try correcting the protocol */ -  sa.sll_protocol = htons (0x00FE); -  rv = sendto(circuit->fd, circuit->snd_stream->data, -	      stream_get_endp (circuit->snd_stream), 0, -	      (struct sockaddr *) &sa, -	      sizeof (struct sockaddr_ll)); -  if (rv < 0) -    { -      zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", -                circuit->interface->name, safe_strerror(errno)); -      if (ERRNO_IO_RETRY(errno)) -        return ISIS_WARNING; -      return ISIS_ERROR; -    } -  return ISIS_OK; +	struct sockaddr_ll sa; +	ssize_t rv; + +	stream_set_getp(circuit->snd_stream, 0); +	memset(&sa, 0, sizeof(struct sockaddr_ll)); +	sa.sll_family = AF_PACKET; +	sa.sll_ifindex = circuit->interface->ifindex; +	sa.sll_halen = ETH_ALEN; +	if (level == 1) +		memcpy(&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); +	else +		memcpy(&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); + + +	/* lets try correcting the protocol */ +	sa.sll_protocol = htons(0x00FE); +	rv = sendto(circuit->fd, circuit->snd_stream->data, +		    stream_get_endp(circuit->snd_stream), 0, +		    (struct sockaddr *)&sa, sizeof(struct sockaddr_ll)); +	if (rv < 0) { +		zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", +			  circuit->interface->name, safe_strerror(errno)); +		if (ERRNO_IO_RETRY(errno)) +			return ISIS_WARNING; +		return ISIS_ERROR; +	} +	return ISIS_OK;  }  #endif /* ISIS_METHOD == ISIS_METHOD_PFPACKET */  | 
