2
* IS-IS Rout(e)ing protocol - isis_pfpacket.c
4
* Copyright (C) 2001,2002 Sampo Saaristo
5
* Tampere University of Technology
6
* Institute of Communications Engineering
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)
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
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.
24
#include <net/ethernet.h> /* the L2 protocols */
25
#include <netpacket/packet.h>
31
#include "isisd/dict.h"
32
#include "isisd/include-netbsd/iso.h"
33
#include "isisd/isis_constants.h"
34
#include "isisd/isis_common.h"
35
#include "isisd/isis_circuit.h"
36
#include "isisd/isis_flags.h"
37
#include "isisd/isisd.h"
38
#include "isisd/isis_constants.h"
39
#include "isisd/isis_circuit.h"
40
#include "isisd/isis_network.h"
44
extern struct zebra_privs_t isisd_privs;
47
* Table 9 - Architectural constants for use with ISO 8802 subnetworks
51
u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 };
52
u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 };
53
u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 };
54
u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 };
56
static char discard_buff[8192];
57
static char sock_buff[8192];
60
* if level is 0 we are joining p2p multicast
61
* FIXME: and the p2p multicast being ???
64
isis_multicast_join (int fd, int registerto, int if_num)
66
struct packet_mreq mreq;
68
memset (&mreq, 0, sizeof (mreq));
69
mreq.mr_ifindex = if_num;
72
mreq.mr_type = PACKET_MR_MULTICAST;
73
mreq.mr_alen = ETH_ALEN;
75
memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN);
76
else if (registerto == 2)
77
memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN);
78
else if (registerto == 3)
79
memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN);
81
memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN);
86
mreq.mr_type = PACKET_MR_ALLMULTI;
89
zlog_debug ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, "
90
"address = %02x:%02x:%02x:%02x:%02x:%02x",
91
fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1],
92
mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4],
94
#endif /* EXTREME_DEBUG */
95
if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
96
sizeof (struct packet_mreq)))
98
zlog_warn ("isis_multicast_join(): setsockopt(): %s", safe_strerror (errno));
106
open_packet_socket (struct isis_circuit *circuit)
108
struct sockaddr_ll s_addr;
109
int fd, retval = ISIS_OK;
111
fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL));
114
zlog_warn ("open_packet_socket(): socket() failed %s",
115
safe_strerror (errno));
120
* Bind to the physical interface
122
memset (&s_addr, 0, sizeof (struct sockaddr_ll));
123
s_addr.sll_family = AF_PACKET;
124
s_addr.sll_protocol = htons (ETH_P_ALL);
125
s_addr.sll_ifindex = circuit->interface->ifindex;
127
if (bind (fd, (struct sockaddr *) (&s_addr),
128
sizeof (struct sockaddr_ll)) < 0)
130
zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno));
136
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
139
* Join to multicast groups
141
* 8.4.2 - Broadcast subnetwork IIH PDUs
142
* FIXME: is there a case only one will fail??
144
if (circuit->circuit_is_type & IS_LEVEL_1)
146
/* joining ALL_L1_ISS */
147
retval = isis_multicast_join (circuit->fd, 1,
148
circuit->interface->ifindex);
149
/* joining ALL_ISS */
150
retval = isis_multicast_join (circuit->fd, 3,
151
circuit->interface->ifindex);
153
if (circuit->circuit_is_type & IS_LEVEL_2)
154
/* joining ALL_L2_ISS */
155
retval = isis_multicast_join (circuit->fd, 2,
156
circuit->interface->ifindex);
161
isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
168
* Create the socket and set the tx/rx funcs
171
isis_sock_init (struct isis_circuit *circuit)
173
int retval = ISIS_OK;
175
if (isisd_privs.change (ZPRIVS_RAISE))
176
zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno));
178
retval = open_packet_socket (circuit);
180
if (retval != ISIS_OK)
182
zlog_warn ("%s: could not initialize the socket", __func__);
186
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
188
circuit->tx = isis_send_pdu_bcast;
189
circuit->rx = isis_recv_pdu_bcast;
191
else if (circuit->circ_type == CIRCUIT_T_P2P)
193
circuit->tx = isis_send_pdu_p2p;
194
circuit->rx = isis_recv_pdu_p2p;
198
zlog_warn ("isis_sock_init(): unknown circuit type");
199
retval = ISIS_WARNING;
204
if (isisd_privs.change (ZPRIVS_LOWER))
205
zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno));
211
llc_check (u_char * llc)
213
if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3)
220
isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
222
int bytesread, addr_len;
223
struct sockaddr_ll s_addr;
226
addr_len = sizeof (s_addr);
228
memset (&s_addr, 0, sizeof (struct sockaddr_ll));
230
bytesread = recvfrom (circuit->fd, (void *) &llc,
232
(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
236
zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s",
237
circuit->fd, safe_strerror (errno));
238
zlog_warn ("circuit is %s", circuit->interface->name);
239
zlog_warn ("circuit fd %d", circuit->fd);
240
zlog_warn ("bytesread %d", bytesread);
241
/* get rid of the packet */
242
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
246
* Filtering by llc field, discard packets sent by this host (other circuit)
248
if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING)
250
/* Read the packet into discard buff */
251
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
253
zlog_warn ("isis_recv_pdu_bcast(): read() failed");
257
/* on lan we have to read to the static buff first */
258
bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0,
259
(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
261
/* then we lose the LLC */
262
stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN);
264
memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen);
270
isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
272
int bytesread, addr_len;
273
struct sockaddr_ll s_addr;
275
memset (&s_addr, 0, sizeof (struct sockaddr_ll));
276
addr_len = sizeof (s_addr);
278
/* we can read directly to the stream */
279
bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd,
280
circuit->interface->mtu, 0,
281
(struct sockaddr *) &s_addr,
282
(socklen_t *) &addr_len);
284
if (s_addr.sll_pkttype == PACKET_OUTGOING)
286
/* Read the packet into discard buff */
287
bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
289
zlog_warn ("isis_recv_pdu_p2p(): read() failed");
293
/* If we don't have protocol type 0x00FE which is
294
* ISO over GRE we exit with pain :)
296
if (ntohs (s_addr.sll_protocol) != 0x00FE)
298
zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X",
299
ntohs (s_addr.sll_protocol));
303
memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen);
309
isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
311
/* we need to do the LLC in here because of P2P circuits, which will
315
struct sockaddr_ll sa;
317
stream_set_getp (circuit->snd_stream, 0);
318
memset (&sa, 0, sizeof (struct sockaddr_ll));
319
sa.sll_family = AF_PACKET;
320
sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
321
sa.sll_ifindex = circuit->interface->ifindex;
322
sa.sll_halen = ETH_ALEN;
324
memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
326
memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
328
/* on a broadcast circuit */
329
/* first we put the LLC in */
334
/* then we copy the data */
335
memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
336
stream_get_endp (circuit->snd_stream));
338
/* now we can send this */
339
written = sendto (circuit->fd, sock_buff,
340
stream_get_endp(circuit->snd_stream) + LLC_LEN, 0,
341
(struct sockaddr *) &sa, sizeof (struct sockaddr_ll));
347
isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
351
struct sockaddr_ll sa;
353
stream_set_getp (circuit->snd_stream, 0);
354
memset (&sa, 0, sizeof (struct sockaddr_ll));
355
sa.sll_family = AF_PACKET;
356
sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
357
sa.sll_ifindex = circuit->interface->ifindex;
358
sa.sll_halen = ETH_ALEN;
360
memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
362
memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
365
/* lets try correcting the protocol */
366
sa.sll_protocol = htons (0x00FE);
367
written = sendto (circuit->fd, circuit->snd_stream->data,
368
stream_get_endp (circuit->snd_stream), 0,
369
(struct sockaddr *) &sa,
370
sizeof (struct sockaddr_ll));