1 diff --git a/ChangeLog b/ChangeLog |
|
2 index 38ea66d..ad1c40c 100644 |
|
3 --- ChangeLog |
|
4 +++ ChangeLog |
|
5 @@ -1,3 +1,8 @@ |
|
6 +2007-08-07 James Carlson <[email protected]> |
|
7 + |
|
8 + * configure.ac: Added support for separate link-layer access |
|
9 + mechanisms in isisd. |
|
10 + |
|
11 2007-07-27 Paul Jakma <[email protected]> |
|
12 |
|
13 * configure.ac: Bump version to 0.99.8 |
|
14 diff --git a/configure.ac b/configure.ac |
|
15 index 857f415..437767e 100755 |
|
16 --- configure.ac |
|
17 +++ configure.ac |
|
18 @@ -750,6 +750,35 @@ |
|
19 AC_SUBST(KERNEL_METHOD) |
|
20 AC_SUBST(OTHER_METHOD) |
|
21 |
|
22 +dnl -------------------------- |
|
23 +dnl Determine IS-IS I/O method |
|
24 +dnl -------------------------- |
|
25 +AC_CHECK_HEADER(net/bpf.h) |
|
26 +AC_CHECK_HEADER(sys/dlpi.h) |
|
27 +AC_MSG_CHECKING(zebra IS-IS I/O method) |
|
28 +if test x"$opsys" = x"gnu-linux"; then |
|
29 + AC_MSG_RESULT(pfpacket) |
|
30 + ISIS_METHOD=isis_pfpacket.o |
|
31 +elif test x"$opsys" = x"sol2-6" -o x"$opsys" = x"sol8"; then |
|
32 + AC_MSG_RESULT(DLPI) |
|
33 + ISIS_METHOD="isis_dlpi.o" |
|
34 +else |
|
35 + if test $ac_cv_header_net_bpf_h = no; then |
|
36 + if test $ac_cv_header_sys_dlpi_h = no; then |
|
37 + AC_MSG_RESULT(none) |
|
38 + AC_MSG_WARN([*** IS-IS support will not be built ***]) |
|
39 + ISISD="" |
|
40 + else |
|
41 + AC_MSG_RESULT(DLPI) |
|
42 + fi |
|
43 + ISIS_METHOD="isis_dlpi.o" |
|
44 + else |
|
45 + AC_MSG_RESULT(BPF) |
|
46 + ISIS_METHOD="isis_bpf.o" |
|
47 + fi |
|
48 +fi |
|
49 +AC_SUBST(ISIS_METHOD) |
|
50 + |
|
51 dnl ------------------------------------ |
|
52 dnl check for broken CMSG_FIRSTHDR macro |
|
53 dnl ------------------------------------ |
|
54 diff --git a/isisd/ChangeLog b/isisd/ChangeLog |
|
55 index 8797af1..c2482f0 100644 |
|
56 --- isisd/ChangeLog |
|
57 +++ isisd/ChangeLog |
|
58 @@ -1,3 +1,20 @@ |
|
59 +2008-01-29 James Carlson <[email protected]> |
|
60 + |
|
61 + * Fix bug #437, assert due to bogus index management |
|
62 + * isis_flags.c: (flags_initialize) new |
|
63 + * (flags_get_index) fix off by one, leading to list assert |
|
64 + on null node data. |
|
65 + (flags_free_index) ditto. |
|
66 + * isisd.c: (isis_area_create) use flags_initialize |
|
67 + (isis_area_destroy) deconfigure circuits when |
|
68 + taking down area. |
|
69 + |
|
70 +2007-07-18 James Carlson <[email protected]> |
|
71 + |
|
72 + * isis_network.c: split up into isis_bpf.c, isis_dlpi.c, and |
|
73 + isis_pfpacket.c, selected by autoconf, and added DLPI support. |
|
74 + * (general) Fixed to allow compilation and use on Solaris. |
|
75 + |
|
76 2006-12-08 Hannes Gredler <[email protected]> |
|
77 |
|
78 * isis_adjacency.c: (isis_new_adj) Allow NULL snpa argument. |
|
79 diff --git a/isisd/Makefile.am b/isisd/Makefile.am |
|
80 index 1dd5493..859facd 100644 |
|
81 --- isisd/Makefile.am |
|
82 +++ isisd/Makefile.am |
|
83 @@ -9,9 +9,11 @@ noinst_LIBRARIES = libisis.a |
|
84 sbin_PROGRAMS = isisd |
|
85 SUBDIRS = topology |
|
86 |
|
87 +isis_method = @ISIS_METHOD@ |
|
88 + |
|
89 libisis_a_SOURCES = \ |
|
90 isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \ |
|
91 - isis_tlv.c isisd.c isis_misc.c isis_network.c isis_zebra.c isis_dr.c \ |
|
92 + isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \ |
|
93 isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \ |
|
94 isis_spf.c isis_route.c isis_routemap.c |
|
95 |
|
96 @@ -26,7 +28,11 @@ noinst_HEADERS = \ |
|
97 isisd_SOURCES = \ |
|
98 isis_main.c $(libisis_a_SOURCES) |
|
99 |
|
100 -isisd_LDADD = @ISIS_TOPOLOGY_LIB@ ../lib/libzebra.la @LIBCAP@ |
|
101 +isisd_LDADD = $(isis_method) @ISIS_TOPOLOGY_LIB@ ../lib/libzebra.la @LIBCAP@ |
|
102 + |
|
103 +isisd_DEPENDENCIES = $(isis_method) |
|
104 + |
|
105 +EXTRA_DIST = isis_bpf.c isis_dlpi.c isis_pfpacket.c |
|
106 |
|
107 examplesdir = $(exampledir) |
|
108 dist_examples_DATA = isisd.conf.sample |
|
109 diff --git a/isisd/dict.c b/isisd/dict.c |
|
110 index a333d3e..6c3e1e7 100644 |
|
111 --- isisd/dict.c |
|
112 +++ isisd/dict.c |
|
113 @@ -14,12 +14,13 @@ |
|
114 * into proprietary software; there is no requirement for such software to |
|
115 * contain a copyright notice related to this source. |
|
116 * |
|
117 - * $Id: dict.c,v 1.4 2005/09/25 12:04:25 hasso Exp $ |
|
118 - * $Name: $ |
|
119 + * $Id$ |
|
120 + * $Name$ |
|
121 */ |
|
122 |
|
123 #include <stdlib.h> |
|
124 #include <stddef.h> |
|
125 +#include "zebra.h" |
|
126 #include "zassert.h" |
|
127 #define DICT_IMPLEMENTATION |
|
128 #include "dict.h" |
|
129 diff --git a/isisd/include-netbsd/iso.h b/isisd/include-netbsd/iso.h |
|
130 index 714b42d..1a80aec 100644 |
|
131 --- isisd/include-netbsd/iso.h |
|
132 +++ isisd/include-netbsd/iso.h |
|
133 @@ -192,7 +192,13 @@ extern struct protosw isosw[]; |
|
134 #else |
|
135 /* user utilities definitions from the iso library */ |
|
136 |
|
137 +#ifdef SUNOS_5 |
|
138 +#define __P(x) x |
|
139 +#define __BEGIN_DECLS |
|
140 +#define __END_DECLS |
|
141 +#else |
|
142 #include <sys/cdefs.h> |
|
143 +#endif |
|
144 |
|
145 __BEGIN_DECLS |
|
146 struct iso_addr *iso_addr __P((const char *)); |
|
147 diff --git a/isisd/isisd.c b/isisd/isisd.c |
|
148 index 714b42d..1a80aec 100644 |
|
149 --- isisd/isisd.c |
|
150 +++ isisd/isisd.c |
|
151 @@ -130,7 +130,7 @@ |
|
152 area->circuit_list = list_new (); |
|
153 area->area_addrs = list_new (); |
|
154 THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1); |
|
155 - area->flags.maxindex = -1; |
|
156 + flags_initialize (&area->flags); |
|
157 /* |
|
158 * Default values |
|
159 */ |
|
160 @@ -215,7 +215,11 @@ |
|
161 if (area->circuit_list) |
|
162 { |
|
163 for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit)) |
|
164 - isis_circuit_del (circuit); |
|
165 + { |
|
166 + /* The fact that it's in circuit_list means that it was configured */ |
|
167 + isis_circuit_deconfigure (circuit, area); |
|
168 + isis_circuit_del (circuit); |
|
169 + } |
|
170 |
|
171 list_delete (area->circuit_list); |
|
172 } |
|
173 diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c |
|
174 new file mode 100644 |
|
175 index 0000000..e66ac98 |
|
176 --- /dev/null |
|
177 +++ isisd/isis_bpf.c |
|
178 @@ -0,0 +1,340 @@ |
|
179 +/* |
|
180 + * IS-IS Rout(e)ing protocol - isis_bpf.c |
|
181 + * |
|
182 + * Copyright (C) 2001,2002 Sampo Saaristo |
|
183 + * Tampere University of Technology |
|
184 + * Institute of Communications Engineering |
|
185 + * |
|
186 + * This program is free software; you can redistribute it and/or modify it |
|
187 + * under the terms of the GNU General Public Licenseas published by the Free |
|
188 + * Software Foundation; either version 2 of the License, or (at your option) |
|
189 + * any later version. |
|
190 + * |
|
191 + * This program is distributed in the hope that it will be useful,but WITHOUT |
|
192 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
193 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|
194 + * more details. |
|
195 + |
|
196 + * You should have received a copy of the GNU General Public License along |
|
197 + * with this program; if not, write to the Free Software Foundation, Inc., |
|
198 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
199 + */ |
|
200 + |
|
201 +#include <zebra.h> |
|
202 +#include <net/if.h> |
|
203 +#include <netinet/if_ether.h> |
|
204 +#include <sys/time.h> |
|
205 +#include <sys/ioctl.h> |
|
206 +#include <net/bpf.h> |
|
207 + |
|
208 +#include "log.h" |
|
209 +#include "stream.h" |
|
210 +#include "if.h" |
|
211 + |
|
212 +#include "isisd/dict.h" |
|
213 +#include "isisd/include-netbsd/iso.h" |
|
214 +#include "isisd/isis_constants.h" |
|
215 +#include "isisd/isis_common.h" |
|
216 +#include "isisd/isis_circuit.h" |
|
217 +#include "isisd/isis_flags.h" |
|
218 +#include "isisd/isisd.h" |
|
219 +#include "isisd/isis_constants.h" |
|
220 +#include "isisd/isis_circuit.h" |
|
221 +#include "isisd/isis_network.h" |
|
222 + |
|
223 +#include "privs.h" |
|
224 + |
|
225 +extern struct zebra_privs_t isisd_privs; |
|
226 + |
|
227 +struct bpf_insn llcfilter[] = { |
|
228 + BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN), /* check first byte */ |
|
229 + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), |
|
230 + BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), |
|
231 + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3), /* check second byte */ |
|
232 + BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), |
|
233 + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ |
|
234 + BPF_STMT (BPF_RET + BPF_K, (u_int) - 1), |
|
235 + BPF_STMT (BPF_RET + BPF_K, 0) |
|
236 +}; |
|
237 +int readblen = 0; |
|
238 +u_char *readbuff = NULL; |
|
239 + |
|
240 +/* |
|
241 + * Table 9 - Architectural constants for use with ISO 8802 subnetworks |
|
242 + * ISO 10589 - 8.4.8 |
|
243 + */ |
|
244 + |
|
245 +u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; |
|
246 +u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; |
|
247 +u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; |
|
248 +u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; |
|
249 + |
|
250 +static char sock_buff[8192]; |
|
251 + |
|
252 +static int |
|
253 +open_bpf_dev (struct isis_circuit *circuit) |
|
254 +{ |
|
255 + int i = 0, fd; |
|
256 + char bpfdev[128]; |
|
257 + struct ifreq ifr; |
|
258 + u_int16_t blen; |
|
259 + int true = 1, false = 0; |
|
260 + struct timeval timeout; |
|
261 + struct bpf_program bpf_prog; |
|
262 + |
|
263 + do |
|
264 + { |
|
265 + (void) snprintf (bpfdev, sizeof (bpfdev), "/dev/bpf%d", i++); |
|
266 + fd = open (bpfdev, O_RDWR); |
|
267 + } |
|
268 + while (fd < 0 && errno == EBUSY); |
|
269 + |
|
270 + if (fd < 0) |
|
271 + { |
|
272 + zlog_warn ("open_bpf_dev(): failed to create bpf socket: %s", |
|
273 + safe_strerror (errno)); |
|
274 + return ISIS_WARNING; |
|
275 + } |
|
276 + |
|
277 + zlog_debug ("Opened BPF device %s", bpfdev); |
|
278 + |
|
279 + memcpy (ifr.ifr_name, circuit->interface->name, sizeof (ifr.ifr_name)); |
|
280 + if (ioctl (fd, BIOCSETIF, (caddr_t) & ifr) < 0) |
|
281 + { |
|
282 + zlog_warn ("open_bpf_dev(): failed to bind to interface: %s", |
|
283 + safe_strerror (errno)); |
|
284 + return ISIS_WARNING; |
|
285 + } |
|
286 + |
|
287 + if (ioctl (fd, BIOCGBLEN, (caddr_t) & blen) < 0) |
|
288 + { |
|
289 + zlog_warn ("failed to get BPF buffer len"); |
|
290 + blen = circuit->interface->mtu; |
|
291 + } |
|
292 + |
|
293 + readblen = blen; |
|
294 + |
|
295 + if (readbuff == NULL) |
|
296 + readbuff = malloc (blen); |
|
297 + |
|
298 + zlog_debug ("BPF buffer len = %u", blen); |
|
299 + |
|
300 + /* BPF(4): reads return immediately upon packet reception. |
|
301 + * Otherwise, a read will block until either the kernel |
|
302 + * buffer becomes full or a timeout occurs. |
|
303 + */ |
|
304 + if (ioctl (fd, BIOCIMMEDIATE, (caddr_t) & true) < 0) |
|
305 + { |
|
306 + zlog_warn ("failed to set BPF dev to immediate mode"); |
|
307 + } |
|
308 + |
|
309 +#ifdef BIOCSSEESENT |
|
310 + /* |
|
311 + * We want to see only incoming packets |
|
312 + */ |
|
313 + if (ioctl (fd, BIOCSSEESENT, (caddr_t) & false) < 0) |
|
314 + { |
|
315 + zlog_warn ("failed to set BPF dev to incoming only mode"); |
|
316 + } |
|
317 +#endif |
|
318 + |
|
319 + /* |
|
320 + * ...but all of them |
|
321 + */ |
|
322 + if (ioctl (fd, BIOCPROMISC, (caddr_t) & true) < 0) |
|
323 + { |
|
324 + zlog_warn ("failed to set BPF dev to promiscuous mode"); |
|
325 + } |
|
326 + |
|
327 + /* |
|
328 + * If the buffer length is smaller than our mtu, lets try to increase it |
|
329 + */ |
|
330 + if (blen < circuit->interface->mtu) |
|
331 + { |
|
332 + if (ioctl (fd, BIOCSBLEN, &circuit->interface->mtu) < 0) |
|
333 + { |
|
334 + zlog_warn ("failed to set BPF buffer len (%u to %u)", blen, |
|
335 + circuit->interface->mtu); |
|
336 + } |
|
337 + } |
|
338 + |
|
339 + /* |
|
340 + * Set a timeout parameter - hope this helps select() |
|
341 + */ |
|
342 + timeout.tv_sec = 600; |
|
343 + timeout.tv_usec = 0; |
|
344 + if (ioctl (fd, BIOCSRTIMEOUT, (caddr_t) & timeout) < 0) |
|
345 + { |
|
346 + zlog_warn ("failed to set BPF device timeout"); |
|
347 + } |
|
348 + |
|
349 + /* |
|
350 + * And set the filter |
|
351 + */ |
|
352 + memset (&bpf_prog, 0, sizeof (struct bpf_program)); |
|
353 + bpf_prog.bf_len = 8; |
|
354 + bpf_prog.bf_insns = &(llcfilter[0]); |
|
355 + if (ioctl (fd, BIOCSETF, (caddr_t) & bpf_prog) < 0) |
|
356 + { |
|
357 + zlog_warn ("open_bpf_dev(): failed to install filter: %s", |
|
358 + safe_strerror (errno)); |
|
359 + return ISIS_WARNING; |
|
360 + } |
|
361 + |
|
362 + assert (fd > 0); |
|
363 + |
|
364 + circuit->fd = fd; |
|
365 + |
|
366 + return ISIS_OK; |
|
367 +} |
|
368 + |
|
369 +/* |
|
370 + * Create the socket and set the tx/rx funcs |
|
371 + */ |
|
372 +int |
|
373 +isis_sock_init (struct isis_circuit *circuit) |
|
374 +{ |
|
375 + int retval = ISIS_OK; |
|
376 + |
|
377 + if (isisd_privs.change (ZPRIVS_RAISE)) |
|
378 + zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno)); |
|
379 + |
|
380 + retval = open_bpf_dev (circuit); |
|
381 + |
|
382 + if (retval != ISIS_OK) |
|
383 + { |
|
384 + zlog_warn ("%s: could not initialize the socket", __func__); |
|
385 + goto end; |
|
386 + } |
|
387 + |
|
388 + if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
|
389 + { |
|
390 + circuit->tx = isis_send_pdu_bcast; |
|
391 + circuit->rx = isis_recv_pdu_bcast; |
|
392 + } |
|
393 + else if (circuit->circ_type == CIRCUIT_T_P2P) |
|
394 + { |
|
395 + circuit->tx = isis_send_pdu_p2p; |
|
396 + circuit->rx = isis_recv_pdu_p2p; |
|
397 + } |
|
398 + else |
|
399 + { |
|
400 + zlog_warn ("isis_sock_init(): unknown circuit type"); |
|
401 + retval = ISIS_WARNING; |
|
402 + goto end; |
|
403 + } |
|
404 + |
|
405 +end: |
|
406 + if (isisd_privs.change (ZPRIVS_LOWER)) |
|
407 + zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno)); |
|
408 + |
|
409 + return retval; |
|
410 +} |
|
411 + |
|
412 +int |
|
413 +isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) |
|
414 +{ |
|
415 + int bytesread = 0, bytestoread, offset, one = 1; |
|
416 + struct bpf_hdr *bpf_hdr; |
|
417 + |
|
418 + assert (circuit->fd > 0); |
|
419 + |
|
420 + if (ioctl (circuit->fd, FIONREAD, (caddr_t) & bytestoread) < 0) |
|
421 + { |
|
422 + zlog_warn ("ioctl() FIONREAD failed: %s", safe_strerror (errno)); |
|
423 + } |
|
424 + |
|
425 + if (bytestoread) |
|
426 + { |
|
427 + bytesread = read (circuit->fd, readbuff, readblen); |
|
428 + } |
|
429 + if (bytesread < 0) |
|
430 + { |
|
431 + zlog_warn ("isis_recv_pdu_bcast(): read() failed: %s", |
|
432 + safe_strerror (errno)); |
|
433 + return ISIS_WARNING; |
|
434 + } |
|
435 + |
|
436 + if (bytesread == 0) |
|
437 + return ISIS_WARNING; |
|
438 + |
|
439 + bpf_hdr = (struct bpf_hdr *) readbuff; |
|
440 + |
|
441 + assert (bpf_hdr->bh_caplen == bpf_hdr->bh_datalen); |
|
442 + |
|
443 + offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN; |
|
444 + |
|
445 + /* then we lose the BPF, LLC and ethernet headers */ |
|
446 + stream_write (circuit->rcv_stream, readbuff + offset, |
|
447 + bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN); |
|
448 + stream_set_getp (circuit->rcv_stream, 0); |
|
449 + |
|
450 + memcpy (ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN, |
|
451 + ETHER_ADDR_LEN); |
|
452 + |
|
453 + if (ioctl (circuit->fd, BIOCFLUSH, &one) < 0) |
|
454 + zlog_warn ("Flushing failed: %s", safe_strerror (errno)); |
|
455 + |
|
456 + return ISIS_OK; |
|
457 +} |
|
458 + |
|
459 +int |
|
460 +isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) |
|
461 +{ |
|
462 + int bytesread; |
|
463 + |
|
464 + bytesread = stream_read (circuit->rcv_stream, circuit->fd, |
|
465 + circuit->interface->mtu); |
|
466 + |
|
467 + if (bytesread < 0) |
|
468 + { |
|
469 + zlog_warn ("isis_recv_pdu_p2p(): read () failed: %s", safe_strerror (errno)); |
|
470 + return ISIS_WARNING; |
|
471 + } |
|
472 + |
|
473 + return ISIS_OK; |
|
474 +} |
|
475 + |
|
476 +int |
|
477 +isis_send_pdu_bcast (struct isis_circuit *circuit, int level) |
|
478 +{ |
|
479 + struct ether_header *eth; |
|
480 + int written; |
|
481 + |
|
482 + stream_set_getp (circuit->snd_stream, 0); |
|
483 + |
|
484 + /* |
|
485 + * First the eth header |
|
486 + */ |
|
487 + eth = (struct ether_header *) sock_buff; |
|
488 + if (level == 1) |
|
489 + memcpy (eth->ether_dhost, ALL_L1_ISS, ETHER_ADDR_LEN); |
|
490 + else |
|
491 + memcpy (eth->ether_dhost, ALL_L2_ISS, ETHER_ADDR_LEN); |
|
492 + memcpy (eth->ether_shost, circuit->u.bc.snpa, ETHER_ADDR_LEN); |
|
493 + eth->ether_type = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN); |
|
494 + |
|
495 + /* |
|
496 + * Then the LLC |
|
497 + */ |
|
498 + sock_buff[ETHER_HDR_LEN] = ISO_SAP; |
|
499 + sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP; |
|
500 + sock_buff[ETHER_HDR_LEN + 2] = 0x03; |
|
501 + |
|
502 + /* then we copy the data */ |
|
503 + memcpy (sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, |
|
504 + stream_get_endp (circuit->snd_stream)); |
|
505 + |
|
506 + /* now we can send this */ |
|
507 + written = write (circuit->fd, sock_buff, |
|
508 + stream_get_endp (circuit->snd_stream) |
|
509 + + LLC_LEN + ETHER_HDR_LEN); |
|
510 + |
|
511 + return ISIS_OK; |
|
512 +} |
|
513 + |
|
514 +int |
|
515 +isis_send_pdu_p2p (struct isis_circuit *circuit, int level) |
|
516 +{ |
|
517 + return ISIS_OK; |
|
518 +} |
|
519 diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c |
|
520 index fe3eb82..af24988 100644 |
|
521 --- isisd/isis_circuit.c |
|
522 +++ isisd/isis_circuit.c |
|
523 @@ -26,6 +26,10 @@ |
|
524 #include <netinet/if_ether.h> |
|
525 #endif |
|
526 |
|
527 +#ifndef ETHER_ADDR_LEN |
|
528 +#define ETHER_ADDR_LEN ETHERADDRL |
|
529 +#endif |
|
530 + |
|
531 #include "log.h" |
|
532 #include "memory.h" |
|
533 #include "if.h" |
|
534 @@ -381,11 +385,13 @@ isis_circuit_if_add (struct isis_circuit *circuit, struct interface *ifp) |
|
535 * Get the Hardware Address |
|
536 */ |
|
537 #ifdef HAVE_STRUCT_SOCKADDR_DL |
|
538 +#ifndef SUNOS_5 |
|
539 if (circuit->interface->sdl.sdl_alen != ETHER_ADDR_LEN) |
|
540 zlog_warn ("unsupported link layer"); |
|
541 else |
|
542 memcpy (circuit->u.bc.snpa, LLADDR (&circuit->interface->sdl), |
|
543 ETH_ALEN); |
|
544 +#endif |
|
545 #else |
|
546 if (circuit->interface->hw_addr_len != ETH_ALEN) |
|
547 { |
|
548 @@ -447,10 +453,12 @@ isis_circuit_update_params (struct isis_circuit *circuit, |
|
549 * Get the Hardware Address |
|
550 */ |
|
551 #ifdef HAVE_STRUCT_SOCKADDR_DL |
|
552 +#ifndef SUNOS_5 |
|
553 if (circuit->interface->sdl.sdl_alen != ETHER_ADDR_LEN) |
|
554 zlog_warn ("unsupported link layer"); |
|
555 else |
|
556 memcpy (circuit->u.bc.snpa, LLADDR (&circuit->interface->sdl), ETH_ALEN); |
|
557 +#endif |
|
558 #else |
|
559 if (circuit->interface->hw_addr_len != ETH_ALEN) |
|
560 { |
|
561 diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h |
|
562 index b5ef269..a7e719f 100644 |
|
563 --- isisd/isis_circuit.h |
|
564 +++ isisd/isis_circuit.h |
|
565 @@ -69,6 +69,7 @@ struct isis_circuit |
|
566 struct isis_area *area; /* back pointer to the area */ |
|
567 struct interface *interface; /* interface info from z */ |
|
568 int fd; /* IS-IS l1/2 socket */ |
|
569 + int sap_length; /* SAP length for DLPI */ |
|
570 struct nlpids nlpids; |
|
571 /* |
|
572 * Threads |
|
573 diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c |
|
574 new file mode 100644 |
|
575 index 0000000..db4383b |
|
576 --- /dev/null |
|
577 +++ isisd/isis_dlpi.c |
|
578 @@ -0,0 +1,607 @@ |
|
579 +/* |
|
580 + * IS-IS Rout(e)ing protocol - isis_dlpi.c |
|
581 + * |
|
582 + * Copyright (C) 2001,2002 Sampo Saaristo |
|
583 + * Tampere University of Technology |
|
584 + * Institute of Communications Engineering |
|
585 + * |
|
586 + * This program is free software; you can redistribute it and/or modify it |
|
587 + * under the terms of the GNU General Public Licenseas published by the Free |
|
588 + * Software Foundation; either version 2 of the License, or (at your option) |
|
589 + * any later version. |
|
590 + * |
|
591 + * This program is distributed in the hope that it will be useful,but WITHOUT |
|
592 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
593 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|
594 + * more details. |
|
595 + |
|
596 + * You should have received a copy of the GNU General Public License along |
|
597 + * with this program; if not, write to the Free Software Foundation, Inc., |
|
598 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
599 + */ |
|
600 + |
|
601 +#include <zebra.h> |
|
602 +#include <net/if.h> |
|
603 +#include <netinet/if_ether.h> |
|
604 +#include <sys/types.h> |
|
605 +#include <unistd.h> |
|
606 +#include <fcntl.h> |
|
607 +#include <stropts.h> |
|
608 +#include <poll.h> |
|
609 +#include <sys/dlpi.h> |
|
610 +#include <sys/pfmod.h> |
|
611 + |
|
612 +#include "log.h" |
|
613 +#include "stream.h" |
|
614 +#include "if.h" |
|
615 + |
|
616 +#include "isisd/dict.h" |
|
617 +#include "isisd/include-netbsd/iso.h" |
|
618 +#include "isisd/isis_constants.h" |
|
619 +#include "isisd/isis_common.h" |
|
620 +#include "isisd/isis_circuit.h" |
|
621 +#include "isisd/isis_flags.h" |
|
622 +#include "isisd/isisd.h" |
|
623 +#include "isisd/isis_constants.h" |
|
624 +#include "isisd/isis_circuit.h" |
|
625 +#include "isisd/isis_network.h" |
|
626 + |
|
627 +#include "privs.h" |
|
628 + |
|
629 +extern struct zebra_privs_t isisd_privs; |
|
630 + |
|
631 +static t_uscalar_t dlpi_ctl[1024]; /* DLPI control messages */ |
|
632 + |
|
633 +/* |
|
634 + * Table 9 - Architectural constants for use with ISO 8802 subnetworks |
|
635 + * ISO 10589 - 8.4.8 |
|
636 + */ |
|
637 + |
|
638 +u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; |
|
639 +u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; |
|
640 +u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; |
|
641 +u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; |
|
642 + |
|
643 +static u_char sock_buff[8192]; |
|
644 + |
|
645 +static u_short pf_filter[] = |
|
646 +{ |
|
647 + ENF_PUSHWORD + 0, /* Get the SSAP/DSAP values */ |
|
648 + ENF_PUSHLIT | ENF_CAND, /* Check them */ |
|
649 + ISO_SAP | (ISO_SAP << 8), |
|
650 + ENF_PUSHWORD + 1, /* Get the control value */ |
|
651 + ENF_PUSHLIT | ENF_AND, /* Isolate it */ |
|
652 +#ifdef _BIG_ENDIAN |
|
653 + 0xFF00, |
|
654 +#else |
|
655 + 0x00FF, |
|
656 +#endif |
|
657 + ENF_PUSHLIT | ENF_CAND, /* Test for expected value */ |
|
658 +#ifdef _BIG_ENDIAN |
|
659 + 0x0300 |
|
660 +#else |
|
661 + 0x0003 |
|
662 +#endif |
|
663 +}; |
|
664 + |
|
665 +/* |
|
666 + * We would like to use something like libdlpi here, but that's not present on |
|
667 + * all versions of Solaris or on any non-Solaris system, so it's nowhere near |
|
668 + * as portable as we'd like. Thus, we use the standards-conformant DLPI |
|
669 + * interfaces plus the (optional; not needed) Solaris packet filter module. |
|
670 + */ |
|
671 + |
|
672 +static void |
|
673 +dlpisend (int fd, const void *cbuf, size_t cbuflen, |
|
674 + const void *dbuf, size_t dbuflen, int flags) |
|
675 +{ |
|
676 + const struct strbuf *ctlptr = NULL; |
|
677 + const struct strbuf *dataptr = NULL; |
|
678 + struct strbuf ctlbuf, databuf; |
|
679 + |
|
680 + if (cbuf != NULL) |
|
681 + { |
|
682 + memset (&ctlbuf, 0, sizeof (ctlbuf)); |
|
683 + ctlbuf.len = cbuflen; |
|
684 + ctlbuf.buf = (void *)cbuf; |
|
685 + ctlptr = &ctlbuf; |
|
686 + } |
|
687 + |
|
688 + if (dbuf != NULL) |
|
689 + { |
|
690 + memset (&databuf, 0, sizeof (databuf)); |
|
691 + databuf.len = dbuflen; |
|
692 + databuf.buf = (void *)dbuf; |
|
693 + dataptr = &databuf; |
|
694 + } |
|
695 + |
|
696 + /* We assume this doesn't happen often and isn't operationally significant */ |
|
697 + if (putmsg (fd, ctlptr, dataptr, flags) == -1) |
|
698 + zlog_debug ("%s: putmsg: %s", __func__, safe_strerror (errno)); |
|
699 +} |
|
700 + |
|
701 +static ssize_t |
|
702 +dlpirctl (int fd) |
|
703 +{ |
|
704 + struct pollfd fds[1]; |
|
705 + struct strbuf ctlbuf, databuf; |
|
706 + int flags, retv; |
|
707 + |
|
708 + do |
|
709 + { |
|
710 + /* Poll is used here in case the device doesn't speak DLPI correctly */ |
|
711 + memset (fds, 0, sizeof (fds)); |
|
712 + fds[0].fd = fd; |
|
713 + fds[0].events = POLLIN | POLLPRI; |
|
714 + if (poll (fds, 1, 1000) <= 0) |
|
715 + return -1; |
|
716 + |
|
717 + memset (&ctlbuf, 0, sizeof (ctlbuf)); |
|
718 + memset (&databuf, 0, sizeof (databuf)); |
|
719 + ctlbuf.maxlen = sizeof (dlpi_ctl); |
|
720 + ctlbuf.buf = (void *)dlpi_ctl; |
|
721 + databuf.maxlen = sizeof (sock_buff); |
|
722 + databuf.buf = (void *)sock_buff; |
|
723 + flags = 0; |
|
724 + retv = getmsg (fd, &ctlbuf, &databuf, &flags); |
|
725 + |
|
726 + if (retv < 0) |
|
727 + return -1; |
|
728 + } |
|
729 + while (ctlbuf.len == 0); |
|
730 + |
|
731 + if (!(retv & MORECTL)) |
|
732 + { |
|
733 + while (retv & MOREDATA) |
|
734 + { |
|
735 + flags = 0; |
|
736 + retv = getmsg (fd, NULL, &databuf, &flags); |
|
737 + } |
|
738 + return ctlbuf.len; |
|
739 + } |
|
740 + |
|
741 + while (retv & MORECTL) |
|
742 + { |
|
743 + flags = 0; |
|
744 + retv = getmsg (fd, &ctlbuf, &databuf, &flags); |
|
745 + } |
|
746 + return -1; |
|
747 +} |
|
748 + |
|
749 +static int |
|
750 +dlpiok (int fd, t_uscalar_t oprim) |
|
751 +{ |
|
752 + int retv; |
|
753 + dl_ok_ack_t *doa = (dl_ok_ack_t *)dlpi_ctl; |
|
754 + |
|
755 + retv = dlpirctl (fd); |
|
756 + if (retv < DL_OK_ACK_SIZE || doa->dl_primitive != DL_OK_ACK || |
|
757 + doa->dl_correct_primitive != oprim) |
|
758 + { |
|
759 + return -1; |
|
760 + } |
|
761 + else |
|
762 + { |
|
763 + return 0; |
|
764 + } |
|
765 +} |
|
766 + |
|
767 +static int |
|
768 +dlpiinfo (int fd) |
|
769 +{ |
|
770 + dl_info_req_t dir; |
|
771 + ssize_t retv; |
|
772 + |
|
773 + memset (&dir, 0, sizeof (dir)); |
|
774 + dir.dl_primitive = DL_INFO_REQ; |
|
775 + /* Info_req uses M_PCPROTO. */ |
|
776 + dlpisend (fd, &dir, sizeof (dir), NULL, 0, RS_HIPRI); |
|
777 + retv = dlpirctl (fd); |
|
778 + if (retv < DL_INFO_ACK_SIZE || dlpi_ctl[0] != DL_INFO_ACK) |
|
779 + return -1; |
|
780 + else |
|
781 + return retv; |
|
782 +} |
|
783 + |
|
784 +static int |
|
785 +dlpiopen (const char *devpath, ssize_t *acklen) |
|
786 +{ |
|
787 + int fd, flags; |
|
788 + |
|
789 + fd = open (devpath, O_RDWR | O_NONBLOCK | O_NOCTTY); |
|
790 + if (fd == -1) |
|
791 + return -1; |
|
792 + |
|
793 + /* All that we want is for the open itself to be non-blocking, not I/O. */ |
|
794 + flags = fcntl (fd, F_GETFL, 0); |
|
795 + if (flags != -1) |
|
796 + fcntl (fd, F_SETFL, flags & ~O_NONBLOCK); |
|
797 + |
|
798 + /* After opening, ask for information */ |
|
799 + if ((*acklen = dlpiinfo (fd)) == -1) |
|
800 + { |
|
801 + close (fd); |
|
802 + return -1; |
|
803 + } |
|
804 + |
|
805 + return fd; |
|
806 +} |
|
807 + |
|
808 +static int |
|
809 +dlpiattach (int fd, int unit) |
|
810 +{ |
|
811 + dl_attach_req_t dar; |
|
812 + |
|
813 + memset (&dar, 0, sizeof (dar)); |
|
814 + dar.dl_primitive = DL_ATTACH_REQ; |
|
815 + dar.dl_ppa = unit; |
|
816 + dlpisend (fd, &dar, sizeof (dar), NULL, 0, 0); |
|
817 + return dlpiok (fd, dar.dl_primitive); |
|
818 +} |
|
819 + |
|
820 +static int |
|
821 +dlpibind (int fd) |
|
822 +{ |
|
823 + dl_bind_req_t dbr; |
|
824 + int retv; |
|
825 + dl_bind_ack_t *dba = (dl_bind_ack_t *)dlpi_ctl; |
|
826 + |
|
827 + memset (&dbr, 0, sizeof (dbr)); |
|
828 + dbr.dl_primitive = DL_BIND_REQ; |
|
829 + dbr.dl_service_mode = DL_CLDLS; |
|
830 + dlpisend (fd, &dbr, sizeof (dbr), NULL, 0, 0); |
|
831 + |
|
832 + retv = dlpirctl (fd); |
|
833 + if (retv < DL_BIND_ACK_SIZE || dba->dl_primitive != DL_BIND_ACK) |
|
834 + return -1; |
|
835 + else |
|
836 + return 0; |
|
837 +} |
|
838 + |
|
839 +static int |
|
840 +dlpimcast (int fd, const u_char *mcaddr) |
|
841 +{ |
|
842 + struct { |
|
843 + dl_enabmulti_req_t der; |
|
844 + u_char addr[ETHERADDRL]; |
|
845 + } dler; |
|
846 + |
|
847 + memset (&dler, 0, sizeof (dler)); |
|
848 + dler.der.dl_primitive = DL_ENABMULTI_REQ; |
|
849 + dler.der.dl_addr_length = sizeof (dler.addr); |
|
850 + dler.der.dl_addr_offset = dler.addr - (u_char *)&dler; |
|
851 + memcpy (dler.addr, mcaddr, sizeof (dler.addr)); |
|
852 + dlpisend (fd, &dler, sizeof (dler), NULL, 0, 0); |
|
853 + return dlpiok (fd, dler.der.dl_primitive); |
|
854 +} |
|
855 + |
|
856 +static int |
|
857 +dlpiaddr (int fd, u_char *addr) |
|
858 +{ |
|
859 + dl_phys_addr_req_t dpar; |
|
860 + dl_phys_addr_ack_t *dpaa = (dl_phys_addr_ack_t *)dlpi_ctl; |
|
861 + int retv; |
|
862 + |
|
863 + memset (&dpar, 0, sizeof (dpar)); |
|
864 + dpar.dl_primitive = DL_PHYS_ADDR_REQ; |
|
865 + dpar.dl_addr_type = DL_CURR_PHYS_ADDR; |
|
866 + dlpisend (fd, &dpar, sizeof (dpar), NULL, 0, 0); |
|
867 + |
|
868 + retv = dlpirctl (fd); |
|
869 + if (retv < DL_PHYS_ADDR_ACK_SIZE || dpaa->dl_primitive != DL_PHYS_ADDR_ACK) |
|
870 + return -1; |
|
871 + |
|
872 + if (dpaa->dl_addr_offset < DL_PHYS_ADDR_ACK_SIZE || |
|
873 + dpaa->dl_addr_length != ETHERADDRL || |
|
874 + dpaa->dl_addr_offset + dpaa->dl_addr_length > retv) |
|
875 + return -1; |
|
876 + |
|
877 + bcopy((char *)dpaa + dpaa->dl_addr_offset, addr, ETHERADDRL); |
|
878 + return 0; |
|
879 +} |
|
880 + |
|
881 +static int |
|
882 +open_dlpi_dev (struct isis_circuit *circuit) |
|
883 +{ |
|
884 + int fd, unit, retval; |
|
885 + char devpath[MAXPATHLEN]; |
|
886 + dl_info_ack_t *dia = (dl_info_ack_t *)dlpi_ctl; |
|
887 + ssize_t acklen; |
|
888 + |
|
889 + /* Only broadcast-type are supported at the moment */ |
|
890 + if (circuit->circ_type != CIRCUIT_T_BROADCAST) |
|
891 + { |
|
892 + zlog_warn ("%s: non-broadcast interface %s", __func__, |
|
893 + circuit->interface->name); |
|
894 + return ISIS_WARNING; |
|
895 + } |
|
896 + |
|
897 + /* Try first as Style 1 */ |
|
898 + (void) snprintf(devpath, sizeof (devpath), "/dev/%s", |
|
899 + circuit->interface->name); |
|
900 + unit = -1; |
|
901 + fd = dlpiopen (devpath, &acklen); |
|
902 + |
|
903 + /* If that fails, try again as Style 2 */ |
|
904 + if (fd == -1) |
|
905 + { |
|
906 + char *cp; |
|
907 + |
|
908 + cp = devpath + strlen (devpath); |
|
909 + while (--cp >= devpath && isdigit(*cp)) |
|
910 + ; |
|
911 + unit = strtol(cp, NULL, 0); |
|
912 + *cp = '\0'; |
|
913 + fd = dlpiopen (devpath, &acklen); |
|
914 + |
|
915 + /* If that too fails, then the device really doesn't exist */ |
|
916 + if (fd == -1) |
|
917 + { |
|
918 + zlog_warn ("%s: unknown interface %s", __func__, |
|
919 + circuit->interface->name); |
|
920 + return ISIS_WARNING; |
|
921 + } |
|
922 + |
|
923 + /* Double check the DLPI style */ |
|
924 + if (dia->dl_provider_style != DL_STYLE2) |
|
925 + { |
|
926 + zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 2", |
|
927 + circuit->interface->name, devpath); |
|
928 + close (fd); |
|
929 + return ISIS_WARNING; |
|
930 + } |
|
931 + |
|
932 + /* If it succeeds, then we need to attach to the unit specified */ |
|
933 + dlpiattach (fd, unit); |
|
934 + |
|
935 + /* Reget the information, as it may be different per node */ |
|
936 + if ((acklen = dlpiinfo (fd)) == -1) |
|
937 + { |
|
938 + close (fd); |
|
939 + return ISIS_WARNING; |
|
940 + } |
|
941 + } |
|
942 + else |
|
943 + { |
|
944 + /* Double check the DLPI style */ |
|
945 + if (dia->dl_provider_style != DL_STYLE1) |
|
946 + { |
|
947 + zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 1", |
|
948 + circuit->interface->name, devpath); |
|
949 + close (fd); |
|
950 + return ISIS_WARNING; |
|
951 + } |
|
952 + } |
|
953 + |
|
954 + /* Check that the interface we've got is the kind we expect */ |
|
955 + if ((dia->dl_sap_length != 2 && dia->dl_sap_length != -2) || |
|
956 + dia->dl_service_mode != DL_CLDLS || dia->dl_addr_length != ETHERADDRL + 2 || |
|
957 + dia->dl_brdcst_addr_length != ETHERADDRL) |
|
958 + { |
|
959 + zlog_warn ("%s: unsupported interface type for %s", __func__, |
|
960 + circuit->interface->name); |
|
961 + close (fd); |
|
962 + return ISIS_WARNING; |
|
963 + } |
|
964 + switch (dia->dl_mac_type) |
|
965 + { |
|
966 + case DL_CSMACD: |
|
967 + case DL_ETHER: |
|
968 + case DL_100VG: |
|
969 + case DL_100VGTPR: |
|
970 + case DL_ETH_CSMA: |
|
971 + case DL_100BT: |
|
972 + break; |
|
973 + default: |
|
974 + zlog_warn ("%s: unexpected mac type on %s: %d", __func__, |
|
975 + circuit->interface->name, dia->dl_mac_type); |
|
976 + close (fd); |
|
977 + return ISIS_WARNING; |
|
978 + } |
|
979 + |
|
980 + circuit->sap_length = dia->dl_sap_length; |
|
981 + |
|
982 + /* |
|
983 + * The local hardware address is something that should be provided by way of |
|
984 + * sockaddr_dl for the interface, but isn't on Solaris. We set it here based |
|
985 + * on DLPI's reported address to avoid roto-tilling the world. |
|
986 + * (Note that isis_circuit_if_add on Solaris doesn't set the snpa.) |
|
987 + * |
|
988 + * Unfortunately, GLD is broken and doesn't provide the address after attach, |
|
989 + * so we need to be careful and use DL_PHYS_ADDR_REQ instead. |
|
990 + */ |
|
991 + if (dlpiaddr (fd, circuit->u.bc.snpa) == -1) |
|
992 + { |
|
993 + zlog_warn ("open_dlpi_dev(): interface %s: unable to get MAC address", |
|
994 + circuit->interface->name); |
|
995 + close (fd); |
|
996 + return ISIS_WARNING; |
|
997 + } |
|
998 + |
|
999 + /* Now bind to SAP 0. This gives us 802-type traffic. */ |
|
1000 + if (dlpibind (fd) == -1) |
|
1001 + { |
|
1002 + zlog_warn ("%s: cannot bind SAP 0 on %s", __func__, |
|
1003 + circuit->interface->name); |
|
1004 + close (fd); |
|
1005 + return ISIS_WARNING; |
|
1006 + } |
|
1007 + |
|
1008 + /* |
|
1009 + * Join to multicast groups according to |
|
1010 + * 8.4.2 - Broadcast subnetwork IIH PDUs |
|
1011 + */ |
|
1012 + retval = 0; |
|
1013 + if (circuit->circuit_is_type & IS_LEVEL_1) |
|
1014 + { |
|
1015 + retval |= dlpimcast (fd, ALL_L1_ISS); |
|
1016 + retval |= dlpimcast (fd, ALL_ISS); |
|
1017 + } |
|
1018 + if (circuit->circuit_is_type & IS_LEVEL_2) |
|
1019 + retval |= dlpimcast (fd, ALL_L2_ISS); |
|
1020 + |
|
1021 + if (retval != 0) |
|
1022 + { |
|
1023 + zlog_warn ("%s: unable to join multicast on %s", __func__, |
|
1024 + circuit->interface->name); |
|
1025 + close (fd); |
|
1026 + return ISIS_WARNING; |
|
1027 + } |
|
1028 + |
|
1029 + /* Push on the packet filter to avoid stray 802 packets */ |
|
1030 + if (ioctl (fd, I_PUSH, "pfmod") == 0) |
|
1031 + { |
|
1032 + struct packetfilt pfil; |
|
1033 + |
|
1034 + pfil.Pf_Priority = 0; |
|
1035 + pfil.Pf_FilterLen = sizeof (pf_filter) / sizeof (u_short); |
|
1036 + memcpy (pfil.Pf_Filter, pf_filter, sizeof (pf_filter)); |
|
1037 + ioctl (fd, PFIOCSETF, &pfil); |
|
1038 + } |
|
1039 + |
|
1040 + circuit->fd = fd; |
|
1041 + |
|
1042 + return ISIS_OK; |
|
1043 +} |
|
1044 + |
|
1045 +/* |
|
1046 + * Create the socket and set the tx/rx funcs |
|
1047 + */ |
|
1048 +int |
|
1049 +isis_sock_init (struct isis_circuit *circuit) |
|
1050 +{ |
|
1051 + int retval = ISIS_OK; |
|
1052 + |
|
1053 + if (isisd_privs.change (ZPRIVS_RAISE)) |
|
1054 + zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno)); |
|
1055 + |
|
1056 + retval = open_dlpi_dev (circuit); |
|
1057 + |
|
1058 + if (retval != ISIS_OK) |
|
1059 + { |
|
1060 + zlog_warn ("%s: could not initialize the socket", __func__); |
|
1061 + goto end; |
|
1062 + } |
|
1063 + |
|
1064 + if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
|
1065 + { |
|
1066 + circuit->tx = isis_send_pdu_bcast; |
|
1067 + circuit->rx = isis_recv_pdu_bcast; |
|
1068 + } |
|
1069 + else |
|
1070 + { |
|
1071 + zlog_warn ("isis_sock_init(): unknown circuit type"); |
|
1072 + retval = ISIS_WARNING; |
|
1073 + goto end; |
|
1074 + } |
|
1075 + |
|
1076 +end: |
|
1077 + if (isisd_privs.change (ZPRIVS_LOWER)) |
|
1078 + zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno)); |
|
1079 + |
|
1080 + return retval; |
|
1081 +} |
|
1082 + |
|
1083 +int |
|
1084 +isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) |
|
1085 +{ |
|
1086 + struct pollfd fds[1]; |
|
1087 + struct strbuf ctlbuf, databuf; |
|
1088 + int flags, retv; |
|
1089 + dl_unitdata_ind_t *dui = (dl_unitdata_ind_t *)dlpi_ctl; |
|
1090 + |
|
1091 + memset (fds, 0, sizeof (fds)); |
|
1092 + fds[0].fd = circuit->fd; |
|
1093 + fds[0].events = POLLIN | POLLPRI; |
|
1094 + if (poll (fds, 1, 0) <= 0) |
|
1095 + return ISIS_WARNING; |
|
1096 + |
|
1097 + memset (&ctlbuf, 0, sizeof (ctlbuf)); |
|
1098 + memset (&databuf, 0, sizeof (databuf)); |
|
1099 + ctlbuf.maxlen = sizeof (dlpi_ctl); |
|
1100 + ctlbuf.buf = (void *)dlpi_ctl; |
|
1101 + databuf.maxlen = sizeof (sock_buff); |
|
1102 + databuf.buf = (void *)sock_buff; |
|
1103 + flags = 0; |
|
1104 + retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags); |
|
1105 + |
|
1106 + if (retv < 0) |
|
1107 + { |
|
1108 + zlog_warn ("isis_recv_pdu_bcast: getmsg failed: %s", |
|
1109 + safe_strerror (errno)); |
|
1110 + return ISIS_WARNING; |
|
1111 + } |
|
1112 + |
|
1113 + if (retv & (MORECTL | MOREDATA)) |
|
1114 + { |
|
1115 + while (retv & (MORECTL | MOREDATA)) |
|
1116 + { |
|
1117 + flags = 0; |
|
1118 + retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags); |
|
1119 + } |
|
1120 + return ISIS_WARNING; |
|
1121 + } |
|
1122 + |
|
1123 + if (ctlbuf.len < DL_UNITDATA_IND_SIZE || |
|
1124 + dui->dl_primitive != DL_UNITDATA_IND) |
|
1125 + return ISIS_WARNING; |
|
1126 + |
|
1127 + if (dui->dl_src_addr_length != ETHERADDRL + 2 || |
|
1128 + dui->dl_src_addr_offset < DL_UNITDATA_IND_SIZE || |
|
1129 + dui->dl_src_addr_offset + dui->dl_src_addr_length > ctlbuf.len) |
|
1130 + return ISIS_WARNING; |
|
1131 + |
|
1132 + memcpy (ssnpa, (char *)dui + dui->dl_src_addr_offset + |
|
1133 + (circuit->sap_length > 0 ? circuit->sap_length : 0), ETHERADDRL); |
|
1134 + |
|
1135 + if (databuf.len < LLC_LEN || sock_buff[0] != ISO_SAP || |
|
1136 + sock_buff[1] != ISO_SAP || sock_buff[2] != 3) |
|
1137 + return ISIS_WARNING; |
|
1138 + |
|
1139 + stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, |
|
1140 + databuf.len - LLC_LEN); |
|
1141 + stream_set_getp (circuit->rcv_stream, 0); |
|
1142 + |
|
1143 + return ISIS_OK; |
|
1144 +} |
|
1145 + |
|
1146 +int |
|
1147 +isis_send_pdu_bcast (struct isis_circuit *circuit, int level) |
|
1148 +{ |
|
1149 + dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl; |
|
1150 + char *dstaddr; |
|
1151 + u_short *dstsap; |
|
1152 + |
|
1153 + stream_set_getp (circuit->snd_stream, 0); |
|
1154 + |
|
1155 + memset (dur, 0, sizeof (*dur)); |
|
1156 + dur->dl_primitive = DL_UNITDATA_REQ; |
|
1157 + dur->dl_dest_addr_length = ETHERADDRL + 2; |
|
1158 + dur->dl_dest_addr_offset = sizeof (*dur); |
|
1159 + |
|
1160 + dstaddr = (char *)(dur + 1); |
|
1161 + if (circuit->sap_length < 0) |
|
1162 + { |
|
1163 + dstsap = (u_short *)(dstaddr + ETHERADDRL); |
|
1164 + } |
|
1165 + else |
|
1166 + { |
|
1167 + dstsap = (u_short *)dstaddr; |
|
1168 + dstaddr += circuit->sap_length; |
|
1169 + } |
|
1170 + if (level == 1) |
|
1171 + memcpy (dstaddr, ALL_L1_ISS, ETHERADDRL); |
|
1172 + else |
|
1173 + memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL); |
|
1174 + /* Note: DLPI SAP values are in host byte order */ |
|
1175 + *dstsap = stream_get_endp (circuit->snd_stream) + LLC_LEN; |
|
1176 + |
|
1177 + sock_buff[0] = ISO_SAP; |
|
1178 + sock_buff[1] = ISO_SAP; |
|
1179 + sock_buff[2] = 0x03; |
|
1180 + memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data, |
|
1181 + stream_get_endp (circuit->snd_stream)); |
|
1182 + dlpisend (circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length, |
|
1183 + sock_buff, stream_get_endp (circuit->snd_stream) + LLC_LEN, 0); |
|
1184 + return ISIS_OK; |
|
1185 +} |
|
1186 diff --git a/isisd/isis_flags.c b/isisd/isis_flags.c |
|
1187 index 1dd5493..859facd 100644 |
|
1188 --- isisd/isis_flags.c |
|
1189 +++ isisd/isis_flags.c |
|
1190 @@ -29,6 +29,13 @@ |
|
1191 #include "isisd/isis_common.h" |
|
1192 #include "isisd/isis_flags.h" |
|
1193 |
|
1194 +void |
|
1195 +flags_initialize (struct flags *flags) |
|
1196 +{ |
|
1197 + flags->maxindex = 0; |
|
1198 + flags->free_idcs = NULL; |
|
1199 +} |
|
1200 + |
|
1201 int |
|
1202 flags_get_index (struct flags *flags) |
|
1203 { |
|
1204 @@ -37,8 +44,7 @@ |
|
1205 |
|
1206 if (flags->free_idcs == NULL || flags->free_idcs->count == 0) |
|
1207 { |
|
1208 - flags->maxindex++; |
|
1209 - index = flags->maxindex; |
|
1210 + index = flags->maxindex++; |
|
1211 } |
|
1212 else |
|
1213 { |
|
1214 @@ -45,6 +51,7 @@ |
|
1215 node = listhead (flags->free_idcs); |
|
1216 index = (int) listgetdata (node); |
|
1217 listnode_delete (flags->free_idcs, (void *) index); |
|
1218 + index--; |
|
1219 } |
|
1220 |
|
1221 return index; |
|
1222 @@ -53,12 +60,18 @@ |
|
1223 void |
|
1224 flags_free_index (struct flags *flags, int index) |
|
1225 { |
|
1226 + if (index + 1 == flags->maxindex) |
|
1227 + { |
|
1228 + flags->maxindex--; |
|
1229 + return; |
|
1230 + } |
|
1231 + |
|
1232 if (flags->free_idcs == NULL) |
|
1233 { |
|
1234 flags->free_idcs = list_new (); |
|
1235 } |
|
1236 |
|
1237 - listnode_add (flags->free_idcs, (void *) index); |
|
1238 + listnode_add (flags->free_idcs, (void *) (index + 1)); |
|
1239 |
|
1240 return; |
|
1241 } |
|
1242 diff --git a/isisd/isis_flags.h b/isisd/isis_flags.h |
|
1243 --- isisd/isis_flags.h |
|
1244 +++ isisd/isis_flags.h |
|
1245 index 1dd5493..859facd 100644 |
|
1246 @@ -28,6 +28,7 @@ |
|
1247 * the support will be achived using the newest drafts */ |
|
1248 #define ISIS_MAX_CIRCUITS 32 /* = 1024 */ /*FIXME:defined in lsp.h as well */ |
|
1249 |
|
1250 +void flags_initialize (struct flags *flags); |
|
1251 struct flags *new_flags (int size); |
|
1252 int flags_get_index (struct flags *flags); |
|
1253 void flags_free_index (struct flags *flags, int index); |
|
1254 diff --git a/isisd/isis_network.c b/isisd/isis_network.c |
|
1255 deleted file mode 100644 |
|
1256 index 56459ec..0000000 |
|
1257 --- isisd/isis_network.c |
|
1258 +++ /dev/null |
|
1259 @@ -1,643 +0,0 @@ |
|
1260 -/* |
|
1261 - * IS-IS Rout(e)ing protocol - isis_network.c |
|
1262 - * |
|
1263 - * Copyright (C) 2001,2002 Sampo Saaristo |
|
1264 - * Tampere University of Technology |
|
1265 - * Institute of Communications Engineering |
|
1266 - * |
|
1267 - * This program is free software; you can redistribute it and/or modify it |
|
1268 - * under the terms of the GNU General Public Licenseas published by the Free |
|
1269 - * Software Foundation; either version 2 of the License, or (at your option) |
|
1270 - * any later version. |
|
1271 - * |
|
1272 - * This program is distributed in the hope that it will be useful,but WITHOUT |
|
1273 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
1274 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|
1275 - * more details. |
|
1276 - |
|
1277 - * You should have received a copy of the GNU General Public License along |
|
1278 - * with this program; if not, write to the Free Software Foundation, Inc., |
|
1279 - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
1280 - */ |
|
1281 - |
|
1282 -#include <zebra.h> |
|
1283 -#ifdef GNU_LINUX |
|
1284 -#include <net/ethernet.h> /* the L2 protocols */ |
|
1285 -#else |
|
1286 -#include <net/if.h> |
|
1287 -#include <netinet/if_ether.h> |
|
1288 -#endif |
|
1289 - |
|
1290 -#include "log.h" |
|
1291 -#include "stream.h" |
|
1292 -#include "if.h" |
|
1293 - |
|
1294 -#include "isisd/dict.h" |
|
1295 -#include "isisd/include-netbsd/iso.h" |
|
1296 -#include "isisd/isis_constants.h" |
|
1297 -#include "isisd/isis_common.h" |
|
1298 -#include "isisd/isis_circuit.h" |
|
1299 -#include "isisd/isis_flags.h" |
|
1300 -#include "isisd/isisd.h" |
|
1301 -#include "isisd/isis_constants.h" |
|
1302 -#include "isisd/isis_circuit.h" |
|
1303 -#include "isisd/isis_network.h" |
|
1304 - |
|
1305 -#include "privs.h" |
|
1306 - |
|
1307 -extern struct zebra_privs_t isisd_privs; |
|
1308 - |
|
1309 -/* |
|
1310 - * On linux we can use the packet(7) sockets, in other OSs we have to do with |
|
1311 - * Berkley Packet Filter (BPF). Please tell me if you can think of a better |
|
1312 - * way... |
|
1313 - */ |
|
1314 -#ifdef GNU_LINUX |
|
1315 -#include <netpacket/packet.h> |
|
1316 -#else |
|
1317 -#include <sys/time.h> |
|
1318 -#include <sys/ioctl.h> |
|
1319 -#include <net/bpf.h> |
|
1320 -struct bpf_insn llcfilter[] = { |
|
1321 - BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN), /* check first byte */ |
|
1322 - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), |
|
1323 - BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), |
|
1324 - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3), /* check second byte */ |
|
1325 - BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), |
|
1326 - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ |
|
1327 - BPF_STMT (BPF_RET + BPF_K, (u_int) - 1), |
|
1328 - BPF_STMT (BPF_RET + BPF_K, 0) |
|
1329 -}; |
|
1330 -int readblen = 0; |
|
1331 -u_char *readbuff = NULL; |
|
1332 -#endif /* GNU_LINUX */ |
|
1333 - |
|
1334 -/* |
|
1335 - * Table 9 - Architectural constans for use with ISO 8802 subnetworks |
|
1336 - * ISO 10589 - 8.4.8 |
|
1337 - */ |
|
1338 - |
|
1339 -u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; |
|
1340 -u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; |
|
1341 -u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; |
|
1342 -u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; |
|
1343 - |
|
1344 -#ifdef GNU_LINUX |
|
1345 -static char discard_buff[8192]; |
|
1346 -#endif |
|
1347 -static char sock_buff[8192]; |
|
1348 - |
|
1349 -/* |
|
1350 - * if level is 0 we are joining p2p multicast |
|
1351 - * FIXME: and the p2p multicast being ??? |
|
1352 - */ |
|
1353 -#ifdef GNU_LINUX |
|
1354 -static int |
|
1355 -isis_multicast_join (int fd, int registerto, int if_num) |
|
1356 -{ |
|
1357 - struct packet_mreq mreq; |
|
1358 - |
|
1359 - memset (&mreq, 0, sizeof (mreq)); |
|
1360 - mreq.mr_ifindex = if_num; |
|
1361 - if (registerto) |
|
1362 - { |
|
1363 - mreq.mr_type = PACKET_MR_MULTICAST; |
|
1364 - mreq.mr_alen = ETH_ALEN; |
|
1365 - if (registerto == 1) |
|
1366 - memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN); |
|
1367 - else if (registerto == 2) |
|
1368 - memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN); |
|
1369 - else if (registerto == 3) |
|
1370 - memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN); |
|
1371 - else |
|
1372 - memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN); |
|
1373 - |
|
1374 - } |
|
1375 - else |
|
1376 - { |
|
1377 - mreq.mr_type = PACKET_MR_ALLMULTI; |
|
1378 - } |
|
1379 -#ifdef EXTREME_DEBUG |
|
1380 - zlog_debug ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, " |
|
1381 - "address = %02x:%02x:%02x:%02x:%02x:%02x", |
|
1382 - fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1], |
|
1383 - mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4], |
|
1384 - mreq.mr_address[5]); |
|
1385 -#endif /* EXTREME_DEBUG */ |
|
1386 - if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, |
|
1387 - sizeof (struct packet_mreq))) |
|
1388 - { |
|
1389 - zlog_warn ("isis_multicast_join(): setsockopt(): %s", safe_strerror (errno)); |
|
1390 - return ISIS_WARNING; |
|
1391 - } |
|
1392 - |
|
1393 - return ISIS_OK; |
|
1394 -} |
|
1395 - |
|
1396 -static int |
|
1397 -open_packet_socket (struct isis_circuit *circuit) |
|
1398 -{ |
|
1399 - struct sockaddr_ll s_addr; |
|
1400 - int fd, retval = ISIS_OK; |
|
1401 - |
|
1402 - fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL)); |
|
1403 - if (fd < 0) |
|
1404 - { |
|
1405 - zlog_warn ("open_packet_socket(): socket() failed %s", |
|
1406 - safe_strerror (errno)); |
|
1407 - return ISIS_WARNING; |
|
1408 - } |
|
1409 - |
|
1410 - /* |
|
1411 - * Bind to the physical interface |
|
1412 - */ |
|
1413 - memset (&s_addr, 0, sizeof (struct sockaddr_ll)); |
|
1414 - s_addr.sll_family = AF_PACKET; |
|
1415 - s_addr.sll_protocol = htons (ETH_P_ALL); |
|
1416 - s_addr.sll_ifindex = circuit->interface->ifindex; |
|
1417 - |
|
1418 - if (bind (fd, (struct sockaddr *) (&s_addr), |
|
1419 - sizeof (struct sockaddr_ll)) < 0) |
|
1420 - { |
|
1421 - zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno)); |
|
1422 - return ISIS_WARNING; |
|
1423 - } |
|
1424 - |
|
1425 - circuit->fd = fd; |
|
1426 - |
|
1427 - if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
|
1428 - { |
|
1429 - /* |
|
1430 - * Join to multicast groups |
|
1431 - * according to |
|
1432 - * 8.4.2 - Broadcast subnetwork IIH PDUs |
|
1433 - * FIXME: is there a case only one will fail?? |
|
1434 - */ |
|
1435 - if (circuit->circuit_is_type & IS_LEVEL_1) |
|
1436 - { |
|
1437 - /* joining ALL_L1_ISS */ |
|
1438 - retval = isis_multicast_join (circuit->fd, 1, |
|
1439 - circuit->interface->ifindex); |
|
1440 - /* joining ALL_ISS */ |
|
1441 - retval = isis_multicast_join (circuit->fd, 3, |
|
1442 - circuit->interface->ifindex); |
|
1443 - } |
|
1444 - if (circuit->circuit_is_type & IS_LEVEL_2) |
|
1445 - /* joining ALL_L2_ISS */ |
|
1446 - retval = isis_multicast_join (circuit->fd, 2, |
|
1447 - circuit->interface->ifindex); |
|
1448 - } |
|
1449 - else |
|
1450 - { |
|
1451 - retval = |
|
1452 - isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex); |
|
1453 - } |
|
1454 - |
|
1455 - return retval; |
|
1456 -} |
|
1457 - |
|
1458 -#else |
|
1459 - |
|
1460 -static int |
|
1461 -open_bpf_dev (struct isis_circuit *circuit) |
|
1462 -{ |
|
1463 - int i = 0, fd; |
|
1464 - char bpfdev[128]; |
|
1465 - struct ifreq ifr; |
|
1466 - u_int16_t blen; |
|
1467 - int true = 1, false = 0; |
|
1468 - struct timeval timeout; |
|
1469 - struct bpf_program bpf_prog; |
|
1470 - |
|
1471 - do |
|
1472 - { |
|
1473 - (void) snprintf (bpfdev, sizeof (bpfdev), "/dev/bpf%d", i++); |
|
1474 - fd = open (bpfdev, O_RDWR); |
|
1475 - } |
|
1476 - while (fd < 0 && errno == EBUSY); |
|
1477 - |
|
1478 - if (fd < 0) |
|
1479 - { |
|
1480 - zlog_warn ("open_bpf_dev(): failed to create bpf socket: %s", |
|
1481 - safe_strerror (errno)); |
|
1482 - return ISIS_WARNING; |
|
1483 - } |
|
1484 - |
|
1485 - zlog_debug ("Opened BPF device %s", bpfdev); |
|
1486 - |
|
1487 - memcpy (ifr.ifr_name, circuit->interface->name, sizeof (ifr.ifr_name)); |
|
1488 - if (ioctl (fd, BIOCSETIF, (caddr_t) & ifr) < 0) |
|
1489 - { |
|
1490 - zlog_warn ("open_bpf_dev(): failed to bind to interface: %s", |
|
1491 - safe_strerror (errno)); |
|
1492 - return ISIS_WARNING; |
|
1493 - } |
|
1494 - |
|
1495 - if (ioctl (fd, BIOCGBLEN, (caddr_t) & blen) < 0) |
|
1496 - { |
|
1497 - zlog_warn ("failed to get BPF buffer len"); |
|
1498 - blen = circuit->interface->mtu; |
|
1499 - } |
|
1500 - |
|
1501 - readblen = blen; |
|
1502 - |
|
1503 - if (readbuff == NULL) |
|
1504 - readbuff = malloc (blen); |
|
1505 - |
|
1506 - zlog_debug ("BPF buffer len = %u", blen); |
|
1507 - |
|
1508 - /* BPF(4): reads return immediately upon packet reception. |
|
1509 - * Otherwise, a read will block until either the kernel |
|
1510 - * buffer becomes full or a timeout occurs. |
|
1511 - */ |
|
1512 - if (ioctl (fd, BIOCIMMEDIATE, (caddr_t) & true) < 0) |
|
1513 - { |
|
1514 - zlog_warn ("failed to set BPF dev to immediate mode"); |
|
1515 - } |
|
1516 - |
|
1517 -#ifdef BIOCSSEESENT |
|
1518 - /* |
|
1519 - * We want to see only incoming packets |
|
1520 - */ |
|
1521 - if (ioctl (fd, BIOCSSEESENT, (caddr_t) & false) < 0) |
|
1522 - { |
|
1523 - zlog_warn ("failed to set BPF dev to incoming only mode"); |
|
1524 - } |
|
1525 -#endif |
|
1526 - |
|
1527 - /* |
|
1528 - * ...but all of them |
|
1529 - */ |
|
1530 - if (ioctl (fd, BIOCPROMISC, (caddr_t) & true) < 0) |
|
1531 - { |
|
1532 - zlog_warn ("failed to set BPF dev to promiscuous mode"); |
|
1533 - } |
|
1534 - |
|
1535 - /* |
|
1536 - * If the buffer length is smaller than our mtu, lets try to increase it |
|
1537 - */ |
|
1538 - if (blen < circuit->interface->mtu) |
|
1539 - { |
|
1540 - if (ioctl (fd, BIOCSBLEN, &circuit->interface->mtu) < 0) |
|
1541 - { |
|
1542 - zlog_warn ("failed to set BPF buffer len (%u to %u)", blen, |
|
1543 - circuit->interface->mtu); |
|
1544 - } |
|
1545 - } |
|
1546 - |
|
1547 - /* |
|
1548 - * Set a timeout parameter - hope this helps select() |
|
1549 - */ |
|
1550 - timeout.tv_sec = 600; |
|
1551 - timeout.tv_usec = 0; |
|
1552 - if (ioctl (fd, BIOCSRTIMEOUT, (caddr_t) & timeout) < 0) |
|
1553 - { |
|
1554 - zlog_warn ("failed to set BPF device timeout"); |
|
1555 - } |
|
1556 - |
|
1557 - /* |
|
1558 - * And set the filter |
|
1559 - */ |
|
1560 - memset (&bpf_prog, 0, sizeof (struct bpf_program)); |
|
1561 - bpf_prog.bf_len = 8; |
|
1562 - bpf_prog.bf_insns = &(llcfilter[0]); |
|
1563 - if (ioctl (fd, BIOCSETF, (caddr_t) & bpf_prog) < 0) |
|
1564 - { |
|
1565 - zlog_warn ("open_bpf_dev(): failed to install filter: %s", |
|
1566 - safe_strerror (errno)); |
|
1567 - return ISIS_WARNING; |
|
1568 - } |
|
1569 - |
|
1570 - assert (fd > 0); |
|
1571 - |
|
1572 - circuit->fd = fd; |
|
1573 - |
|
1574 - return ISIS_OK; |
|
1575 -} |
|
1576 - |
|
1577 -#endif /* GNU_LINUX */ |
|
1578 - |
|
1579 -/* |
|
1580 - * Create the socket and set the tx/rx funcs |
|
1581 - */ |
|
1582 -int |
|
1583 -isis_sock_init (struct isis_circuit *circuit) |
|
1584 -{ |
|
1585 - int retval = ISIS_OK; |
|
1586 - |
|
1587 - if (isisd_privs.change (ZPRIVS_RAISE)) |
|
1588 - zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno)); |
|
1589 - |
|
1590 -#ifdef GNU_LINUX |
|
1591 - retval = open_packet_socket (circuit); |
|
1592 -#else |
|
1593 - retval = open_bpf_dev (circuit); |
|
1594 -#endif |
|
1595 - |
|
1596 - if (retval != ISIS_OK) |
|
1597 - { |
|
1598 - zlog_warn ("%s: could not initialize the socket", __func__); |
|
1599 - goto end; |
|
1600 - } |
|
1601 - |
|
1602 - if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
|
1603 - { |
|
1604 - circuit->tx = isis_send_pdu_bcast; |
|
1605 - circuit->rx = isis_recv_pdu_bcast; |
|
1606 - } |
|
1607 - else if (circuit->circ_type == CIRCUIT_T_P2P) |
|
1608 - { |
|
1609 - circuit->tx = isis_send_pdu_p2p; |
|
1610 - circuit->rx = isis_recv_pdu_p2p; |
|
1611 - } |
|
1612 - else |
|
1613 - { |
|
1614 - zlog_warn ("isis_sock_init(): unknown circuit type"); |
|
1615 - retval = ISIS_WARNING; |
|
1616 - goto end; |
|
1617 - } |
|
1618 - |
|
1619 -end: |
|
1620 - if (isisd_privs.change (ZPRIVS_LOWER)) |
|
1621 - zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno)); |
|
1622 - |
|
1623 - return retval; |
|
1624 -} |
|
1625 - |
|
1626 -static inline int |
|
1627 -llc_check (u_char * llc) |
|
1628 -{ |
|
1629 - if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3) |
|
1630 - return 0; |
|
1631 - |
|
1632 - return 1; |
|
1633 -} |
|
1634 - |
|
1635 -#ifdef GNU_LINUX |
|
1636 -int |
|
1637 -isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) |
|
1638 -{ |
|
1639 - int bytesread, addr_len; |
|
1640 - struct sockaddr_ll s_addr; |
|
1641 - u_char llc[LLC_LEN]; |
|
1642 - |
|
1643 - addr_len = sizeof (s_addr); |
|
1644 - |
|
1645 - memset (&s_addr, 0, sizeof (struct sockaddr_ll)); |
|
1646 - |
|
1647 - bytesread = recvfrom (circuit->fd, (void *) &llc, |
|
1648 - LLC_LEN, MSG_PEEK, |
|
1649 - (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); |
|
1650 - |
|
1651 - if (bytesread < 0) |
|
1652 - { |
|
1653 - zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s", |
|
1654 - circuit->fd, safe_strerror (errno)); |
|
1655 - zlog_warn ("circuit is %s", circuit->interface->name); |
|
1656 - zlog_warn ("circuit fd %d", circuit->fd); |
|
1657 - zlog_warn ("bytesread %d", bytesread); |
|
1658 - /* get rid of the packet */ |
|
1659 - bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); |
|
1660 - return ISIS_WARNING; |
|
1661 - } |
|
1662 - /* |
|
1663 - * Filtering by llc field, discard packets sent by this host (other circuit) |
|
1664 - */ |
|
1665 - if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING) |
|
1666 - { |
|
1667 - /* Read the packet into discard buff */ |
|
1668 - bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); |
|
1669 - if (bytesread < 0) |
|
1670 - zlog_warn ("isis_recv_pdu_bcast(): read() failed"); |
|
1671 - return ISIS_WARNING; |
|
1672 - } |
|
1673 - |
|
1674 - /* on lan we have to read to the static buff first */ |
|
1675 - bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0, |
|
1676 - (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); |
|
1677 - |
|
1678 - /* then we lose the LLC */ |
|
1679 - stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN); |
|
1680 - |
|
1681 - memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); |
|
1682 - |
|
1683 - return ISIS_OK; |
|
1684 -} |
|
1685 - |
|
1686 -int |
|
1687 -isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) |
|
1688 -{ |
|
1689 - int bytesread, addr_len; |
|
1690 - struct sockaddr_ll s_addr; |
|
1691 - |
|
1692 - memset (&s_addr, 0, sizeof (struct sockaddr_ll)); |
|
1693 - addr_len = sizeof (s_addr); |
|
1694 - |
|
1695 - /* we can read directly to the stream */ |
|
1696 - bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd, |
|
1697 - circuit->interface->mtu, 0, |
|
1698 - (struct sockaddr *) &s_addr, |
|
1699 - (socklen_t *) &addr_len); |
|
1700 - |
|
1701 - if (s_addr.sll_pkttype == PACKET_OUTGOING) |
|
1702 - { |
|
1703 - /* Read the packet into discard buff */ |
|
1704 - bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); |
|
1705 - if (bytesread < 0) |
|
1706 - zlog_warn ("isis_recv_pdu_p2p(): read() failed"); |
|
1707 - return ISIS_WARNING; |
|
1708 - } |
|
1709 - |
|
1710 - /* If we don't have protocol type 0x00FE which is |
|
1711 - * ISO over GRE we exit with pain :) |
|
1712 - */ |
|
1713 - if (ntohs (s_addr.sll_protocol) != 0x00FE) |
|
1714 - { |
|
1715 - zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X", |
|
1716 - ntohs (s_addr.sll_protocol)); |
|
1717 - return ISIS_WARNING; |
|
1718 - } |
|
1719 - |
|
1720 - memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); |
|
1721 - |
|
1722 - return ISIS_OK; |
|
1723 -} |
|
1724 - |
|
1725 -int |
|
1726 -isis_send_pdu_bcast (struct isis_circuit *circuit, int level) |
|
1727 -{ |
|
1728 - /* we need to do the LLC in here because of P2P circuits, which will |
|
1729 - * not need it |
|
1730 - */ |
|
1731 - int written = 1; |
|
1732 - struct sockaddr_ll sa; |
|
1733 - |
|
1734 - stream_set_getp (circuit->snd_stream, 0); |
|
1735 - memset (&sa, 0, sizeof (struct sockaddr_ll)); |
|
1736 - sa.sll_family = AF_PACKET; |
|
1737 - sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN); |
|
1738 - sa.sll_ifindex = circuit->interface->ifindex; |
|
1739 - sa.sll_halen = ETH_ALEN; |
|
1740 - if (level == 1) |
|
1741 - memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); |
|
1742 - else |
|
1743 - memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); |
|
1744 - |
|
1745 - /* on a broadcast circuit */ |
|
1746 - /* first we put the LLC in */ |
|
1747 - sock_buff[0] = 0xFE; |
|
1748 - sock_buff[1] = 0xFE; |
|
1749 - sock_buff[2] = 0x03; |
|
1750 - |
|
1751 - /* then we copy the data */ |
|
1752 - memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data, |
|
1753 - stream_get_endp (circuit->snd_stream)); |
|
1754 - |
|
1755 - /* now we can send this */ |
|
1756 - written = sendto (circuit->fd, sock_buff, |
|
1757 - stream_get_endp(circuit->snd_stream) + LLC_LEN, 0, |
|
1758 - (struct sockaddr *) &sa, sizeof (struct sockaddr_ll)); |
|
1759 - |
|
1760 - return ISIS_OK; |
|
1761 -} |
|
1762 - |
|
1763 -int |
|
1764 -isis_send_pdu_p2p (struct isis_circuit *circuit, int level) |
|
1765 -{ |
|
1766 - |
|
1767 - int written = 1; |
|
1768 - struct sockaddr_ll sa; |
|
1769 - |
|
1770 - stream_set_getp (circuit->snd_stream, 0); |
|
1771 - memset (&sa, 0, sizeof (struct sockaddr_ll)); |
|
1772 - sa.sll_family = AF_PACKET; |
|
1773 - sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN); |
|
1774 - sa.sll_ifindex = circuit->interface->ifindex; |
|
1775 - sa.sll_halen = ETH_ALEN; |
|
1776 - if (level == 1) |
|
1777 - memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); |
|
1778 - else |
|
1779 - memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); |
|
1780 - |
|
1781 - |
|
1782 - /* lets try correcting the protocol */ |
|
1783 - sa.sll_protocol = htons (0x00FE); |
|
1784 - written = sendto (circuit->fd, circuit->snd_stream->data, |
|
1785 - stream_get_endp (circuit->snd_stream), 0, |
|
1786 - (struct sockaddr *) &sa, |
|
1787 - sizeof (struct sockaddr_ll)); |
|
1788 - |
|
1789 - return ISIS_OK; |
|
1790 -} |
|
1791 - |
|
1792 -#else |
|
1793 - |
|
1794 -int |
|
1795 -isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) |
|
1796 -{ |
|
1797 - int bytesread = 0, bytestoread, offset, one = 1; |
|
1798 - struct bpf_hdr *bpf_hdr; |
|
1799 - |
|
1800 - assert (circuit->fd > 0); |
|
1801 - |
|
1802 - if (ioctl (circuit->fd, FIONREAD, (caddr_t) & bytestoread) < 0) |
|
1803 - { |
|
1804 - zlog_warn ("ioctl() FIONREAD failed: %s", safe_strerror (errno)); |
|
1805 - } |
|
1806 - |
|
1807 - if (bytestoread) |
|
1808 - { |
|
1809 - bytesread = read (circuit->fd, readbuff, readblen); |
|
1810 - } |
|
1811 - if (bytesread < 0) |
|
1812 - { |
|
1813 - zlog_warn ("isis_recv_pdu_bcast(): read() failed: %s", |
|
1814 - safe_strerror (errno)); |
|
1815 - return ISIS_WARNING; |
|
1816 - } |
|
1817 - |
|
1818 - if (bytesread == 0) |
|
1819 - return ISIS_WARNING; |
|
1820 - |
|
1821 - bpf_hdr = (struct bpf_hdr *) readbuff; |
|
1822 - |
|
1823 - assert (bpf_hdr->bh_caplen == bpf_hdr->bh_datalen); |
|
1824 - |
|
1825 - offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN; |
|
1826 - |
|
1827 - /* then we lose the BPF, LLC and ethernet headers */ |
|
1828 - stream_write (circuit->rcv_stream, readbuff + offset, |
|
1829 - bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN); |
|
1830 - stream_set_getp (circuit->rcv_stream, 0); |
|
1831 - |
|
1832 - memcpy (ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN, |
|
1833 - ETHER_ADDR_LEN); |
|
1834 - |
|
1835 - if (ioctl (circuit->fd, BIOCFLUSH, &one) < 0) |
|
1836 - zlog_warn ("Flushing failed: %s", safe_strerror (errno)); |
|
1837 - |
|
1838 - return ISIS_OK; |
|
1839 -} |
|
1840 - |
|
1841 -int |
|
1842 -isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) |
|
1843 -{ |
|
1844 - int bytesread; |
|
1845 - |
|
1846 - bytesread = stream_read (circuit->rcv_stream, circuit->fd, |
|
1847 - circuit->interface->mtu); |
|
1848 - |
|
1849 - if (bytesread < 0) |
|
1850 - { |
|
1851 - zlog_warn ("isis_recv_pdu_p2p(): read () failed: %s", safe_strerror (errno)); |
|
1852 - return ISIS_WARNING; |
|
1853 - } |
|
1854 - |
|
1855 - return ISIS_OK; |
|
1856 -} |
|
1857 - |
|
1858 -int |
|
1859 -isis_send_pdu_bcast (struct isis_circuit *circuit, int level) |
|
1860 -{ |
|
1861 - struct ether_header *eth; |
|
1862 - int written; |
|
1863 - |
|
1864 - stream_set_getp (circuit->snd_stream, 0); |
|
1865 - |
|
1866 - /* |
|
1867 - * First the eth header |
|
1868 - */ |
|
1869 - eth = (struct ether_header *) sock_buff; |
|
1870 - if (level == 1) |
|
1871 - memcpy (eth->ether_dhost, ALL_L1_ISS, ETHER_ADDR_LEN); |
|
1872 - else |
|
1873 - memcpy (eth->ether_dhost, ALL_L2_ISS, ETHER_ADDR_LEN); |
|
1874 - memcpy (eth->ether_shost, circuit->u.bc.snpa, ETHER_ADDR_LEN); |
|
1875 - eth->ether_type = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN); |
|
1876 - |
|
1877 - /* |
|
1878 - * Then the LLC |
|
1879 - */ |
|
1880 - sock_buff[ETHER_HDR_LEN] = ISO_SAP; |
|
1881 - sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP; |
|
1882 - sock_buff[ETHER_HDR_LEN + 2] = 0x03; |
|
1883 - |
|
1884 - /* then we copy the data */ |
|
1885 - memcpy (sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, |
|
1886 - stream_get_endp (circuit->snd_stream)); |
|
1887 - |
|
1888 - /* now we can send this */ |
|
1889 - written = write (circuit->fd, sock_buff, |
|
1890 - stream_get_endp (circuit->snd_stream) |
|
1891 - + LLC_LEN + ETHER_HDR_LEN); |
|
1892 - |
|
1893 - return ISIS_OK; |
|
1894 -} |
|
1895 - |
|
1896 -int |
|
1897 -isis_send_pdu_p2p (struct isis_circuit *circuit, int level) |
|
1898 -{ |
|
1899 - return ISIS_OK; |
|
1900 -} |
|
1901 - |
|
1902 -#endif /* GNU_LINUX */ |
|
1903 diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h |
|
1904 index 29c7621..95c1ee4 100644 |
|
1905 --- isisd/isis_pdu.h |
|
1906 +++ isisd/isis_pdu.h |
|
1907 @@ -24,6 +24,10 @@ |
|
1908 #ifndef _ZEBRA_ISIS_PDU_H |
|
1909 #define _ZEBRA_ISIS_PDU_H |
|
1910 |
|
1911 +#ifdef __SUNPRO_C |
|
1912 +#pragma pack(1) |
|
1913 +#endif |
|
1914 + |
|
1915 /* |
|
1916 * ISO 9542 - 7.5,7.6 |
|
1917 * |
|
1918 @@ -222,6 +226,10 @@ struct isis_partial_seqnum_hdr |
|
1919 }; |
|
1920 #define ISIS_PSNP_HDRLEN 9 |
|
1921 |
|
1922 +#ifdef __SUNPRO_C |
|
1923 +#pragma pack() |
|
1924 +#endif |
|
1925 + |
|
1926 /* |
|
1927 * Function for receiving IS-IS PDUs |
|
1928 */ |
|
1929 diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c |
|
1930 new file mode 100644 |
|
1931 index 0000000..8752dba |
|
1932 --- /dev/null |
|
1933 +++ isisd/isis_pfpacket.c |
|
1934 @@ -0,0 +1,373 @@ |
|
1935 +/* |
|
1936 + * IS-IS Rout(e)ing protocol - isis_pfpacket.c |
|
1937 + * |
|
1938 + * Copyright (C) 2001,2002 Sampo Saaristo |
|
1939 + * Tampere University of Technology |
|
1940 + * Institute of Communications Engineering |
|
1941 + * |
|
1942 + * This program is free software; you can redistribute it and/or modify it |
|
1943 + * under the terms of the GNU General Public Licenseas published by the Free |
|
1944 + * Software Foundation; either version 2 of the License, or (at your option) |
|
1945 + * any later version. |
|
1946 + * |
|
1947 + * This program is distributed in the hope that it will be useful,but WITHOUT |
|
1948 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
1949 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|
1950 + * more details. |
|
1951 + |
|
1952 + * You should have received a copy of the GNU General Public License along |
|
1953 + * with this program; if not, write to the Free Software Foundation, Inc., |
|
1954 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
1955 + */ |
|
1956 + |
|
1957 +#include <zebra.h> |
|
1958 +#include <net/ethernet.h> /* the L2 protocols */ |
|
1959 +#include <netpacket/packet.h> |
|
1960 + |
|
1961 +#include "log.h" |
|
1962 +#include "stream.h" |
|
1963 +#include "if.h" |
|
1964 + |
|
1965 +#include "isisd/dict.h" |
|
1966 +#include "isisd/include-netbsd/iso.h" |
|
1967 +#include "isisd/isis_constants.h" |
|
1968 +#include "isisd/isis_common.h" |
|
1969 +#include "isisd/isis_circuit.h" |
|
1970 +#include "isisd/isis_flags.h" |
|
1971 +#include "isisd/isisd.h" |
|
1972 +#include "isisd/isis_constants.h" |
|
1973 +#include "isisd/isis_circuit.h" |
|
1974 +#include "isisd/isis_network.h" |
|
1975 + |
|
1976 +#include "privs.h" |
|
1977 + |
|
1978 +extern struct zebra_privs_t isisd_privs; |
|
1979 + |
|
1980 +/* |
|
1981 + * Table 9 - Architectural constants for use with ISO 8802 subnetworks |
|
1982 + * ISO 10589 - 8.4.8 |
|
1983 + */ |
|
1984 + |
|
1985 +u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; |
|
1986 +u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; |
|
1987 +u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; |
|
1988 +u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; |
|
1989 + |
|
1990 +static char discard_buff[8192]; |
|
1991 +static char sock_buff[8192]; |
|
1992 + |
|
1993 +/* |
|
1994 + * if level is 0 we are joining p2p multicast |
|
1995 + * FIXME: and the p2p multicast being ??? |
|
1996 + */ |
|
1997 +static int |
|
1998 +isis_multicast_join (int fd, int registerto, int if_num) |
|
1999 +{ |
|
2000 + struct packet_mreq mreq; |
|
2001 + |
|
2002 + memset (&mreq, 0, sizeof (mreq)); |
|
2003 + mreq.mr_ifindex = if_num; |
|
2004 + if (registerto) |
|
2005 + { |
|
2006 + mreq.mr_type = PACKET_MR_MULTICAST; |
|
2007 + mreq.mr_alen = ETH_ALEN; |
|
2008 + if (registerto == 1) |
|
2009 + memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN); |
|
2010 + else if (registerto == 2) |
|
2011 + memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN); |
|
2012 + else if (registerto == 3) |
|
2013 + memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN); |
|
2014 + else |
|
2015 + memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN); |
|
2016 + |
|
2017 + } |
|
2018 + else |
|
2019 + { |
|
2020 + mreq.mr_type = PACKET_MR_ALLMULTI; |
|
2021 + } |
|
2022 +#ifdef EXTREME_DEBUG |
|
2023 + zlog_debug ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, " |
|
2024 + "address = %02x:%02x:%02x:%02x:%02x:%02x", |
|
2025 + fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1], |
|
2026 + mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4], |
|
2027 + mreq.mr_address[5]); |
|
2028 +#endif /* EXTREME_DEBUG */ |
|
2029 + if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, |
|
2030 + sizeof (struct packet_mreq))) |
|
2031 + { |
|
2032 + zlog_warn ("isis_multicast_join(): setsockopt(): %s", safe_strerror (errno)); |
|
2033 + return ISIS_WARNING; |
|
2034 + } |
|
2035 + |
|
2036 + return ISIS_OK; |
|
2037 +} |
|
2038 + |
|
2039 +static int |
|
2040 +open_packet_socket (struct isis_circuit *circuit) |
|
2041 +{ |
|
2042 + struct sockaddr_ll s_addr; |
|
2043 + int fd, retval = ISIS_OK; |
|
2044 + |
|
2045 + fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL)); |
|
2046 + if (fd < 0) |
|
2047 + { |
|
2048 + zlog_warn ("open_packet_socket(): socket() failed %s", |
|
2049 + safe_strerror (errno)); |
|
2050 + return ISIS_WARNING; |
|
2051 + } |
|
2052 + |
|
2053 + /* |
|
2054 + * Bind to the physical interface |
|
2055 + */ |
|
2056 + memset (&s_addr, 0, sizeof (struct sockaddr_ll)); |
|
2057 + s_addr.sll_family = AF_PACKET; |
|
2058 + s_addr.sll_protocol = htons (ETH_P_ALL); |
|
2059 + s_addr.sll_ifindex = circuit->interface->ifindex; |
|
2060 + |
|
2061 + if (bind (fd, (struct sockaddr *) (&s_addr), |
|
2062 + sizeof (struct sockaddr_ll)) < 0) |
|
2063 + { |
|
2064 + zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno)); |
|
2065 + return ISIS_WARNING; |
|
2066 + } |
|
2067 + |
|
2068 + circuit->fd = fd; |
|
2069 + |
|
2070 + if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
|
2071 + { |
|
2072 + /* |
|
2073 + * Join to multicast groups |
|
2074 + * according to |
|
2075 + * 8.4.2 - Broadcast subnetwork IIH PDUs |
|
2076 + * FIXME: is there a case only one will fail?? |
|
2077 + */ |
|
2078 + if (circuit->circuit_is_type & IS_LEVEL_1) |
|
2079 + { |
|
2080 + /* joining ALL_L1_ISS */ |
|
2081 + retval = isis_multicast_join (circuit->fd, 1, |
|
2082 + circuit->interface->ifindex); |
|
2083 + /* joining ALL_ISS */ |
|
2084 + retval = isis_multicast_join (circuit->fd, 3, |
|
2085 + circuit->interface->ifindex); |
|
2086 + } |
|
2087 + if (circuit->circuit_is_type & IS_LEVEL_2) |
|
2088 + /* joining ALL_L2_ISS */ |
|
2089 + retval = isis_multicast_join (circuit->fd, 2, |
|
2090 + circuit->interface->ifindex); |
|
2091 + } |
|
2092 + else |
|
2093 + { |
|
2094 + retval = |
|
2095 + isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex); |
|
2096 + } |
|
2097 + |
|
2098 + return retval; |
|
2099 +} |
|
2100 + |
|
2101 +/* |
|
2102 + * Create the socket and set the tx/rx funcs |
|
2103 + */ |
|
2104 +int |
|
2105 +isis_sock_init (struct isis_circuit *circuit) |
|
2106 +{ |
|
2107 + int retval = ISIS_OK; |
|
2108 + |
|
2109 + if (isisd_privs.change (ZPRIVS_RAISE)) |
|
2110 + zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno)); |
|
2111 + |
|
2112 + retval = open_packet_socket (circuit); |
|
2113 + |
|
2114 + if (retval != ISIS_OK) |
|
2115 + { |
|
2116 + zlog_warn ("%s: could not initialize the socket", __func__); |
|
2117 + goto end; |
|
2118 + } |
|
2119 + |
|
2120 + if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
|
2121 + { |
|
2122 + circuit->tx = isis_send_pdu_bcast; |
|
2123 + circuit->rx = isis_recv_pdu_bcast; |
|
2124 + } |
|
2125 + else if (circuit->circ_type == CIRCUIT_T_P2P) |
|
2126 + { |
|
2127 + circuit->tx = isis_send_pdu_p2p; |
|
2128 + circuit->rx = isis_recv_pdu_p2p; |
|
2129 + } |
|
2130 + else |
|
2131 + { |
|
2132 + zlog_warn ("isis_sock_init(): unknown circuit type"); |
|
2133 + retval = ISIS_WARNING; |
|
2134 + goto end; |
|
2135 + } |
|
2136 + |
|
2137 +end: |
|
2138 + if (isisd_privs.change (ZPRIVS_LOWER)) |
|
2139 + zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno)); |
|
2140 + |
|
2141 + return retval; |
|
2142 +} |
|
2143 + |
|
2144 +static inline int |
|
2145 +llc_check (u_char * llc) |
|
2146 +{ |
|
2147 + if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3) |
|
2148 + return 0; |
|
2149 + |
|
2150 + return 1; |
|
2151 +} |
|
2152 + |
|
2153 +int |
|
2154 +isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) |
|
2155 +{ |
|
2156 + int bytesread, addr_len; |
|
2157 + struct sockaddr_ll s_addr; |
|
2158 + u_char llc[LLC_LEN]; |
|
2159 + |
|
2160 + addr_len = sizeof (s_addr); |
|
2161 + |
|
2162 + memset (&s_addr, 0, sizeof (struct sockaddr_ll)); |
|
2163 + |
|
2164 + bytesread = recvfrom (circuit->fd, (void *) &llc, |
|
2165 + LLC_LEN, MSG_PEEK, |
|
2166 + (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); |
|
2167 + |
|
2168 + if (bytesread < 0) |
|
2169 + { |
|
2170 + zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s", |
|
2171 + circuit->fd, safe_strerror (errno)); |
|
2172 + zlog_warn ("circuit is %s", circuit->interface->name); |
|
2173 + zlog_warn ("circuit fd %d", circuit->fd); |
|
2174 + zlog_warn ("bytesread %d", bytesread); |
|
2175 + /* get rid of the packet */ |
|
2176 + bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); |
|
2177 + return ISIS_WARNING; |
|
2178 + } |
|
2179 + /* |
|
2180 + * Filtering by llc field, discard packets sent by this host (other circuit) |
|
2181 + */ |
|
2182 + if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING) |
|
2183 + { |
|
2184 + /* Read the packet into discard buff */ |
|
2185 + bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); |
|
2186 + if (bytesread < 0) |
|
2187 + zlog_warn ("isis_recv_pdu_bcast(): read() failed"); |
|
2188 + return ISIS_WARNING; |
|
2189 + } |
|
2190 + |
|
2191 + /* on lan we have to read to the static buff first */ |
|
2192 + bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0, |
|
2193 + (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); |
|
2194 + |
|
2195 + /* then we lose the LLC */ |
|
2196 + stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN); |
|
2197 + |
|
2198 + memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); |
|
2199 + |
|
2200 + return ISIS_OK; |
|
2201 +} |
|
2202 + |
|
2203 +int |
|
2204 +isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) |
|
2205 +{ |
|
2206 + int bytesread, addr_len; |
|
2207 + struct sockaddr_ll s_addr; |
|
2208 + |
|
2209 + memset (&s_addr, 0, sizeof (struct sockaddr_ll)); |
|
2210 + addr_len = sizeof (s_addr); |
|
2211 + |
|
2212 + /* we can read directly to the stream */ |
|
2213 + bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd, |
|
2214 + circuit->interface->mtu, 0, |
|
2215 + (struct sockaddr *) &s_addr, |
|
2216 + (socklen_t *) &addr_len); |
|
2217 + |
|
2218 + if (s_addr.sll_pkttype == PACKET_OUTGOING) |
|
2219 + { |
|
2220 + /* Read the packet into discard buff */ |
|
2221 + bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff)); |
|
2222 + if (bytesread < 0) |
|
2223 + zlog_warn ("isis_recv_pdu_p2p(): read() failed"); |
|
2224 + return ISIS_WARNING; |
|
2225 + } |
|
2226 + |
|
2227 + /* If we don't have protocol type 0x00FE which is |
|
2228 + * ISO over GRE we exit with pain :) |
|
2229 + */ |
|
2230 + if (ntohs (s_addr.sll_protocol) != 0x00FE) |
|
2231 + { |
|
2232 + zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X", |
|
2233 + ntohs (s_addr.sll_protocol)); |
|
2234 + return ISIS_WARNING; |
|
2235 + } |
|
2236 + |
|
2237 + memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); |
|
2238 + |
|
2239 + return ISIS_OK; |
|
2240 +} |
|
2241 + |
|
2242 +int |
|
2243 +isis_send_pdu_bcast (struct isis_circuit *circuit, int level) |
|
2244 +{ |
|
2245 + /* we need to do the LLC in here because of P2P circuits, which will |
|
2246 + * not need it |
|
2247 + */ |
|
2248 + int written = 1; |
|
2249 + struct sockaddr_ll sa; |
|
2250 + |
|
2251 + stream_set_getp (circuit->snd_stream, 0); |
|
2252 + memset (&sa, 0, sizeof (struct sockaddr_ll)); |
|
2253 + sa.sll_family = AF_PACKET; |
|
2254 + sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN); |
|
2255 + sa.sll_ifindex = circuit->interface->ifindex; |
|
2256 + sa.sll_halen = ETH_ALEN; |
|
2257 + if (level == 1) |
|
2258 + memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); |
|
2259 + else |
|
2260 + memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); |
|
2261 + |
|
2262 + /* on a broadcast circuit */ |
|
2263 + /* first we put the LLC in */ |
|
2264 + sock_buff[0] = 0xFE; |
|
2265 + sock_buff[1] = 0xFE; |
|
2266 + sock_buff[2] = 0x03; |
|
2267 + |
|
2268 + /* then we copy the data */ |
|
2269 + memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data, |
|
2270 + stream_get_endp (circuit->snd_stream)); |
|
2271 + |
|
2272 + /* now we can send this */ |
|
2273 + written = sendto (circuit->fd, sock_buff, |
|
2274 + stream_get_endp(circuit->snd_stream) + LLC_LEN, 0, |
|
2275 + (struct sockaddr *) &sa, sizeof (struct sockaddr_ll)); |
|
2276 + |
|
2277 + return ISIS_OK; |
|
2278 +} |
|
2279 + |
|
2280 +int |
|
2281 +isis_send_pdu_p2p (struct isis_circuit *circuit, int level) |
|
2282 +{ |
|
2283 + |
|
2284 + int written = 1; |
|
2285 + struct sockaddr_ll sa; |
|
2286 + |
|
2287 + stream_set_getp (circuit->snd_stream, 0); |
|
2288 + memset (&sa, 0, sizeof (struct sockaddr_ll)); |
|
2289 + sa.sll_family = AF_PACKET; |
|
2290 + sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN); |
|
2291 + sa.sll_ifindex = circuit->interface->ifindex; |
|
2292 + sa.sll_halen = ETH_ALEN; |
|
2293 + if (level == 1) |
|
2294 + memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); |
|
2295 + else |
|
2296 + memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); |
|
2297 + |
|
2298 + |
|
2299 + /* lets try correcting the protocol */ |
|
2300 + sa.sll_protocol = htons (0x00FE); |
|
2301 + written = sendto (circuit->fd, circuit->snd_stream->data, |
|
2302 + stream_get_endp (circuit->snd_stream), 0, |
|
2303 + (struct sockaddr *) &sa, |
|
2304 + sizeof (struct sockaddr_ll)); |
|
2305 + |
|
2306 + return ISIS_OK; |
|
2307 +} |
|
2308 diff --git a/isisd/isis_tlv.h b/isisd/isis_tlv.h |
|
2309 index 951a254..fc9f35f 100644 |
|
2310 --- isisd/isis_tlv.h |
|
2311 +++ isisd/isis_tlv.h |
|
2312 @@ -152,6 +152,10 @@ struct lan_neigh |
|
2313 u_char LAN_addr[6]; |
|
2314 }; |
|
2315 |
|
2316 +#ifdef __SUNPRO_C |
|
2317 +#pragma pack(1) |
|
2318 +#endif |
|
2319 + |
|
2320 /* struct for LSP entry */ |
|
2321 struct lsp_entry |
|
2322 { |
|
2323 @@ -161,6 +165,10 @@ struct lsp_entry |
|
2324 u_int16_t checksum; |
|
2325 } __attribute__ ((packed)); |
|
2326 |
|
2327 +#ifdef __SUNPRO_C |
|
2328 +#pragma pack() |
|
2329 +#endif |
|
2330 + |
|
2331 /* struct for checksum */ |
|
2332 struct checksum |
|
2333 { |
|