Annotation of embedaddon/quagga/isisd/isis_pfpacket.c, revision 1.1
1.1 ! misho 1: /*
! 2: * IS-IS Rout(e)ing protocol - isis_pfpacket.c
! 3: *
! 4: * Copyright (C) 2001,2002 Sampo Saaristo
! 5: * Tampere University of Technology
! 6: * Institute of Communications Engineering
! 7: *
! 8: * This program is free software; you can redistribute it and/or modify it
! 9: * under the terms of the GNU General Public Licenseas published by the Free
! 10: * Software Foundation; either version 2 of the License, or (at your option)
! 11: * any later version.
! 12: *
! 13: * This program is distributed in the hope that it will be useful,but WITHOUT
! 14: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
! 15: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
! 16: * more details.
! 17:
! 18: * You should have received a copy of the GNU General Public License along
! 19: * with this program; if not, write to the Free Software Foundation, Inc.,
! 20: * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
! 21: */
! 22:
! 23: #include <zebra.h>
! 24: #if ISIS_METHOD == ISIS_METHOD_PFPACKET
! 25: #include <net/ethernet.h> /* the L2 protocols */
! 26: #include <netpacket/packet.h>
! 27:
! 28: #include "log.h"
! 29: #include "stream.h"
! 30: #include "if.h"
! 31:
! 32: #include "isisd/dict.h"
! 33: #include "isisd/include-netbsd/iso.h"
! 34: #include "isisd/isis_constants.h"
! 35: #include "isisd/isis_common.h"
! 36: #include "isisd/isis_circuit.h"
! 37: #include "isisd/isis_flags.h"
! 38: #include "isisd/isisd.h"
! 39: #include "isisd/isis_constants.h"
! 40: #include "isisd/isis_circuit.h"
! 41: #include "isisd/isis_network.h"
! 42:
! 43: #include "privs.h"
! 44:
! 45: extern struct zebra_privs_t isisd_privs;
! 46:
! 47: /*
! 48: * Table 9 - Architectural constants for use with ISO 8802 subnetworks
! 49: * ISO 10589 - 8.4.8
! 50: */
! 51:
! 52: u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 };
! 53: u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 };
! 54: u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 };
! 55: u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 };
! 56:
! 57: static char discard_buff[8192];
! 58: static char sock_buff[8192];
! 59:
! 60: /*
! 61: * if level is 0 we are joining p2p multicast
! 62: * FIXME: and the p2p multicast being ???
! 63: */
! 64: static int
! 65: isis_multicast_join (int fd, int registerto, int if_num)
! 66: {
! 67: struct packet_mreq mreq;
! 68:
! 69: memset (&mreq, 0, sizeof (mreq));
! 70: mreq.mr_ifindex = if_num;
! 71: if (registerto)
! 72: {
! 73: mreq.mr_type = PACKET_MR_MULTICAST;
! 74: mreq.mr_alen = ETH_ALEN;
! 75: if (registerto == 1)
! 76: memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN);
! 77: else if (registerto == 2)
! 78: memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN);
! 79: else if (registerto == 3)
! 80: memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN);
! 81: else
! 82: memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN);
! 83:
! 84: }
! 85: else
! 86: {
! 87: mreq.mr_type = PACKET_MR_ALLMULTI;
! 88: }
! 89: #ifdef EXTREME_DEBUG
! 90: zlog_debug ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, "
! 91: "address = %02x:%02x:%02x:%02x:%02x:%02x",
! 92: fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1],
! 93: mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4],
! 94: mreq.mr_address[5]);
! 95: #endif /* EXTREME_DEBUG */
! 96: if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
! 97: sizeof (struct packet_mreq)))
! 98: {
! 99: zlog_warn ("isis_multicast_join(): setsockopt(): %s", safe_strerror (errno));
! 100: return ISIS_WARNING;
! 101: }
! 102:
! 103: return ISIS_OK;
! 104: }
! 105:
! 106: static int
! 107: open_packet_socket (struct isis_circuit *circuit)
! 108: {
! 109: struct sockaddr_ll s_addr;
! 110: int fd, retval = ISIS_OK;
! 111:
! 112: fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL));
! 113: if (fd < 0)
! 114: {
! 115: zlog_warn ("open_packet_socket(): socket() failed %s",
! 116: safe_strerror (errno));
! 117: return ISIS_WARNING;
! 118: }
! 119:
! 120: /*
! 121: * Bind to the physical interface
! 122: */
! 123: memset (&s_addr, 0, sizeof (struct sockaddr_ll));
! 124: s_addr.sll_family = AF_PACKET;
! 125: s_addr.sll_protocol = htons (ETH_P_ALL);
! 126: s_addr.sll_ifindex = circuit->interface->ifindex;
! 127:
! 128: if (bind (fd, (struct sockaddr *) (&s_addr),
! 129: sizeof (struct sockaddr_ll)) < 0)
! 130: {
! 131: zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno));
! 132: return ISIS_WARNING;
! 133: }
! 134:
! 135: circuit->fd = fd;
! 136:
! 137: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
! 138: {
! 139: /*
! 140: * Join to multicast groups
! 141: * according to
! 142: * 8.4.2 - Broadcast subnetwork IIH PDUs
! 143: * FIXME: is there a case only one will fail??
! 144: */
! 145: if (circuit->circuit_is_type & IS_LEVEL_1)
! 146: {
! 147: /* joining ALL_L1_ISS */
! 148: retval = isis_multicast_join (circuit->fd, 1,
! 149: circuit->interface->ifindex);
! 150: /* joining ALL_ISS */
! 151: retval = isis_multicast_join (circuit->fd, 3,
! 152: circuit->interface->ifindex);
! 153: }
! 154: if (circuit->circuit_is_type & IS_LEVEL_2)
! 155: /* joining ALL_L2_ISS */
! 156: retval = isis_multicast_join (circuit->fd, 2,
! 157: circuit->interface->ifindex);
! 158: }
! 159: else
! 160: {
! 161: retval =
! 162: isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
! 163: }
! 164:
! 165: return retval;
! 166: }
! 167:
! 168: /*
! 169: * Create the socket and set the tx/rx funcs
! 170: */
! 171: int
! 172: isis_sock_init (struct isis_circuit *circuit)
! 173: {
! 174: int retval = ISIS_OK;
! 175:
! 176: if (isisd_privs.change (ZPRIVS_RAISE))
! 177: zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno));
! 178:
! 179: retval = open_packet_socket (circuit);
! 180:
! 181: if (retval != ISIS_OK)
! 182: {
! 183: zlog_warn ("%s: could not initialize the socket", __func__);
! 184: goto end;
! 185: }
! 186:
! 187: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
! 188: {
! 189: circuit->tx = isis_send_pdu_bcast;
! 190: circuit->rx = isis_recv_pdu_bcast;
! 191: }
! 192: else if (circuit->circ_type == CIRCUIT_T_P2P)
! 193: {
! 194: circuit->tx = isis_send_pdu_p2p;
! 195: circuit->rx = isis_recv_pdu_p2p;
! 196: }
! 197: else
! 198: {
! 199: zlog_warn ("isis_sock_init(): unknown circuit type");
! 200: retval = ISIS_WARNING;
! 201: goto end;
! 202: }
! 203:
! 204: end:
! 205: if (isisd_privs.change (ZPRIVS_LOWER))
! 206: zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno));
! 207:
! 208: return retval;
! 209: }
! 210:
! 211: static inline int
! 212: llc_check (u_char * llc)
! 213: {
! 214: if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3)
! 215: return 0;
! 216:
! 217: return 1;
! 218: }
! 219:
! 220: int
! 221: isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
! 222: {
! 223: int bytesread, addr_len;
! 224: struct sockaddr_ll s_addr;
! 225: u_char llc[LLC_LEN];
! 226:
! 227: addr_len = sizeof (s_addr);
! 228:
! 229: memset (&s_addr, 0, sizeof (struct sockaddr_ll));
! 230:
! 231: bytesread = recvfrom (circuit->fd, (void *) &llc,
! 232: LLC_LEN, MSG_PEEK,
! 233: (struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
! 234:
! 235: if (!circuit->area) {
! 236: return ISIS_OK;
! 237: }
! 238:
! 239: if (bytesread < 0)
! 240: {
! 241: zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s",
! 242: circuit->fd, safe_strerror (errno));
! 243: zlog_warn ("circuit is %s", circuit->interface->name);
! 244: zlog_warn ("circuit fd %d", circuit->fd);
! 245: zlog_warn ("bytesread %d", bytesread);
! 246: /* get rid of the packet */
! 247: bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
! 248: return ISIS_WARNING;
! 249: }
! 250: /*
! 251: * Filtering by llc field, discard packets sent by this host (other circuit)
! 252: */
! 253: if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING)
! 254: {
! 255: /* Read the packet into discard buff */
! 256: bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
! 257: if (bytesread < 0)
! 258: zlog_warn ("isis_recv_pdu_bcast(): read() failed");
! 259: return ISIS_WARNING;
! 260: }
! 261:
! 262: /* on lan we have to read to the static buff first */
! 263: bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0,
! 264: (struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
! 265:
! 266: /* then we lose the LLC */
! 267: stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN);
! 268:
! 269: memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen);
! 270:
! 271: return ISIS_OK;
! 272: }
! 273:
! 274: int
! 275: isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
! 276: {
! 277: int bytesread, addr_len;
! 278: struct sockaddr_ll s_addr;
! 279:
! 280: memset (&s_addr, 0, sizeof (struct sockaddr_ll));
! 281: addr_len = sizeof (s_addr);
! 282:
! 283: /* we can read directly to the stream */
! 284: bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd,
! 285: circuit->interface->mtu, 0,
! 286: (struct sockaddr *) &s_addr,
! 287: (socklen_t *) &addr_len);
! 288:
! 289: if (s_addr.sll_pkttype == PACKET_OUTGOING)
! 290: {
! 291: /* Read the packet into discard buff */
! 292: bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
! 293: if (bytesread < 0)
! 294: zlog_warn ("isis_recv_pdu_p2p(): read() failed");
! 295: return ISIS_WARNING;
! 296: }
! 297:
! 298: /* If we don't have protocol type 0x00FE which is
! 299: * ISO over GRE we exit with pain :)
! 300: */
! 301: if (ntohs (s_addr.sll_protocol) != 0x00FE)
! 302: {
! 303: zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X",
! 304: ntohs (s_addr.sll_protocol));
! 305: return ISIS_WARNING;
! 306: }
! 307:
! 308: memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen);
! 309:
! 310: return ISIS_OK;
! 311: }
! 312:
! 313: int
! 314: isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
! 315: {
! 316: /* we need to do the LLC in here because of P2P circuits, which will
! 317: * not need it
! 318: */
! 319: int written = 1;
! 320: struct sockaddr_ll sa;
! 321:
! 322: stream_set_getp (circuit->snd_stream, 0);
! 323: memset (&sa, 0, sizeof (struct sockaddr_ll));
! 324: sa.sll_family = AF_PACKET;
! 325: sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
! 326: sa.sll_ifindex = circuit->interface->ifindex;
! 327: sa.sll_halen = ETH_ALEN;
! 328: if (level == 1)
! 329: memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
! 330: else
! 331: memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
! 332:
! 333: /* on a broadcast circuit */
! 334: /* first we put the LLC in */
! 335: sock_buff[0] = 0xFE;
! 336: sock_buff[1] = 0xFE;
! 337: sock_buff[2] = 0x03;
! 338:
! 339: /* then we copy the data */
! 340: memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
! 341: stream_get_endp (circuit->snd_stream));
! 342:
! 343: /* now we can send this */
! 344: written = sendto (circuit->fd, sock_buff,
! 345: stream_get_endp(circuit->snd_stream) + LLC_LEN, 0,
! 346: (struct sockaddr *) &sa, sizeof (struct sockaddr_ll));
! 347:
! 348: return ISIS_OK;
! 349: }
! 350:
! 351: int
! 352: isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
! 353: {
! 354:
! 355: int written = 1;
! 356: struct sockaddr_ll sa;
! 357:
! 358: stream_set_getp (circuit->snd_stream, 0);
! 359: memset (&sa, 0, sizeof (struct sockaddr_ll));
! 360: sa.sll_family = AF_PACKET;
! 361: sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
! 362: sa.sll_ifindex = circuit->interface->ifindex;
! 363: sa.sll_halen = ETH_ALEN;
! 364: if (level == 1)
! 365: memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
! 366: else
! 367: memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
! 368:
! 369:
! 370: /* lets try correcting the protocol */
! 371: sa.sll_protocol = htons (0x00FE);
! 372: written = sendto (circuit->fd, circuit->snd_stream->data,
! 373: stream_get_endp (circuit->snd_stream), 0,
! 374: (struct sockaddr *) &sa,
! 375: sizeof (struct sockaddr_ll));
! 376:
! 377: return ISIS_OK;
! 378: }
! 379:
! 380: #endif /* ISIS_METHOD == ISIS_METHOD_PFPACKET */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>