Annotation of embedaddon/quagga/isisd/isis_pfpacket.c, revision 1.1.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>