source: trunk/minix/servers/inet/generic/psip.c@ 11

Last change on this file since 11 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 18.0 KB
Line 
1/*
2generic/psip.c
3
4Implementation of a pseudo IP device.
5
6Created: Apr 22, 1993 by Philip Homburg
7
8Copyright 1995 Philip Homburg
9*/
10
11#include "inet.h"
12#include "assert.h"
13#include "buf.h"
14#include "event.h"
15#include "type.h"
16#include "ip_int.h"
17#include "psip.h"
18#include "sr.h"
19
20THIS_FILE
21
22typedef struct psip_port
23{
24 int pp_flags;
25 int pp_ipdev;
26 int pp_opencnt;
27 struct psip_fd *pp_rd_head;
28 struct psip_fd *pp_rd_tail;
29 acc_t *pp_promisc_head;
30 acc_t *pp_promisc_tail;
31} psip_port_t;
32
33#define PPF_EMPTY 0
34#define PPF_CONFIGURED 1
35#define PPF_ENABLED 2
36#define PPF_PROMISC 4
37
38#define PSIP_FD_NR (1*IP_PORT_MAX)
39
40typedef struct psip_fd
41{
42 int pf_flags;
43 int pf_srfd;
44 psip_port_t *pf_port;
45 get_userdata_t pf_get_userdata;
46 put_userdata_t pf_put_userdata;
47 struct psip_fd *pf_rd_next;
48 size_t pf_rd_count;
49 nwio_psipopt_t pf_psipopt;
50} psip_fd_t;
51
52#define PFF_EMPTY 0
53#define PFF_INUSE 1
54#define PFF_READ_IP 2
55#define PFF_PROMISC 4
56#define PFF_NEXTHOP 8
57
58PRIVATE psip_port_t *psip_port_table;
59PRIVATE psip_fd_t psip_fd_table[PSIP_FD_NR];
60
61FORWARD int psip_open ARGS(( int port, int srfd,
62 get_userdata_t get_userdata, put_userdata_t put_userdata,
63 put_pkt_t pkt_pkt, select_res_t select_res ));
64FORWARD int psip_ioctl ARGS(( int fd, ioreq_t req ));
65FORWARD int psip_read ARGS(( int fd, size_t count ));
66FORWARD int psip_write ARGS(( int fd, size_t count ));
67FORWARD int psip_select ARGS(( int port_nr, unsigned operations ));
68FORWARD void psip_close ARGS(( int fd ));
69FORWARD int psip_cancel ARGS(( int fd, int which_operation ));
70FORWARD void promisc_restart_read ARGS(( psip_port_t *psip_port ));
71FORWARD int psip_setopt ARGS(( psip_fd_t *psip_fd, nwio_psipopt_t *newoptp ));
72FORWARD void psip_buffree ARGS(( int priority ));
73FORWARD void check_promisc ARGS(( psip_port_t *psip_port ));
74#ifdef BUF_CONSISTENCY_CHECK
75FORWARD void psip_bufcheck ARGS(( void ));
76#endif
77FORWARD void reply_thr_put ARGS(( psip_fd_t *psip_fd, int reply,
78 int for_ioctl ));
79FORWARD void reply_thr_get ARGS(( psip_fd_t *psip_fd, int reply,
80 int for_ioctl ));
81
82PUBLIC void psip_prep()
83{
84 psip_port_table= alloc(psip_conf_nr * sizeof(psip_port_table[0]));
85}
86
87PUBLIC void psip_init()
88{
89 int i;
90 psip_port_t *psip_port;
91 psip_fd_t *psip_fd;
92
93 for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
94 psip_port->pp_flags= PPF_EMPTY;
95
96 for (i=0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
97 psip_fd->pf_flags= PFF_EMPTY;
98
99 for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
100 {
101 psip_port->pp_flags |= PPF_CONFIGURED;
102 psip_port->pp_opencnt= 0;
103 psip_port->pp_rd_head= NULL;
104 psip_port->pp_promisc_head= NULL;
105 }
106
107#ifndef BUF_CONSISTENCY_CHECK
108 bf_logon(psip_buffree);
109#else
110 bf_logon(psip_buffree, psip_bufcheck);
111#endif
112}
113
114PUBLIC int psip_enable(port_nr, ip_port_nr)
115int port_nr;
116int ip_port_nr;
117{
118 psip_port_t *psip_port;
119
120 assert(port_nr >= 0);
121 if (port_nr >= psip_conf_nr)
122 return -1;
123
124 psip_port= &psip_port_table[port_nr];
125 if (!(psip_port->pp_flags &PPF_CONFIGURED))
126 return -1;
127
128 psip_port->pp_ipdev= ip_port_nr;
129 psip_port->pp_flags |= PPF_ENABLED;
130
131 sr_add_minor(if2minor(psip_conf[port_nr].pc_ifno, PSIP_DEV_OFF),
132 port_nr, psip_open, psip_close, psip_read,
133 psip_write, psip_ioctl, psip_cancel, psip_select);
134
135 return NW_OK;
136}
137
138PUBLIC int psip_send(port_nr, dest, pack)
139int port_nr;
140ipaddr_t dest;
141acc_t *pack;
142{
143 psip_port_t *psip_port;
144 psip_fd_t *psip_fd, *mark_fd;
145 int i, result, result1;
146 size_t buf_size, extrasize;
147 acc_t *hdr_pack, *acc;
148 psip_io_hdr_t *hdr;
149
150 assert(port_nr >= 0 && port_nr < psip_conf_nr);
151 psip_port= &psip_port_table[port_nr];
152
153 if (psip_port->pp_opencnt == 0)
154 {
155 bf_afree(pack);
156 return NW_OK;
157 }
158
159 for(;;)
160 {
161 mark_fd= psip_port->pp_rd_tail;
162
163 for(i= 0; i<PSIP_FD_NR; i++)
164 {
165 psip_fd= psip_port->pp_rd_head;
166 if (!psip_fd)
167 return NW_SUSPEND;
168 psip_port->pp_rd_head= psip_fd->pf_rd_next;
169 if (!(psip_fd->pf_flags & PFF_PROMISC))
170 break;
171 psip_fd->pf_rd_next= NULL;
172 if (psip_port->pp_rd_head == NULL)
173 psip_port->pp_rd_head= psip_fd;
174 else
175 psip_port->pp_rd_tail->pf_rd_next= psip_fd;
176 psip_port->pp_rd_tail= psip_fd;
177 if (psip_fd == mark_fd)
178 return NW_SUSPEND;
179 }
180 if (i == PSIP_FD_NR)
181 ip_panic(( "psip_send: loop" ));
182
183 assert(psip_fd->pf_flags & PFF_READ_IP);
184 psip_fd->pf_flags &= ~PFF_READ_IP;
185
186 if (psip_fd->pf_flags & PFF_NEXTHOP)
187 extrasize= sizeof(dest);
188 else
189 extrasize= 0;
190
191 buf_size= bf_bufsize(pack);
192 if (buf_size+extrasize <= psip_fd->pf_rd_count)
193 {
194 if (psip_port->pp_flags & PPF_PROMISC)
195 {
196 /* Deal with promiscuous mode. */
197 hdr_pack= bf_memreq(sizeof(*hdr));
198 hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
199 memset(hdr, '\0', sizeof(*hdr));
200 hdr->pih_flags |= PF_LOC2REM;
201 hdr->pih_nexthop= dest;
202
203 pack->acc_linkC++;
204 hdr_pack->acc_next= pack;
205 hdr_pack->acc_ext_link= NULL;
206 if (psip_port->pp_promisc_head)
207 {
208 /* Append at the end. */
209 psip_port->pp_promisc_tail->
210 acc_ext_link= hdr_pack;
211 psip_port->pp_promisc_tail= hdr_pack;
212 }
213 else
214 {
215 /* First packet. */
216 psip_port->pp_promisc_head= hdr_pack;
217 psip_port->pp_promisc_tail= hdr_pack;
218 if (psip_port->pp_rd_head)
219 promisc_restart_read(psip_port);
220 }
221 }
222
223 if (extrasize)
224 {
225 /* Prepend nexthop address */
226 acc= bf_memreq(sizeof(dest));
227 *(ipaddr_t *)(ptr2acc_data(acc))= dest;
228 acc->acc_next= pack;
229 pack= acc; acc= NULL;
230 buf_size += extrasize;
231 }
232
233 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
234 (size_t)0, pack, FALSE);
235 if (result == NW_OK)
236 result= buf_size;
237 }
238 else
239 result= EPACKSIZE;
240
241 result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
242 (size_t)result, NULL, FALSE);
243 assert(result1 == NW_OK);
244 if (result == EPACKSIZE)
245 continue;
246 return NW_OK;
247 }
248 return NW_SUSPEND;
249}
250
251PRIVATE int psip_open(port, srfd, get_userdata, put_userdata, put_pkt,
252 select_res)
253int port;
254int srfd;
255get_userdata_t get_userdata;
256put_userdata_t put_userdata;
257put_pkt_t put_pkt;
258select_res_t select_res;
259{
260 psip_port_t *psip_port;
261 psip_fd_t *psip_fd;
262 int i;
263
264 assert(port >= 0 && port < psip_conf_nr);
265 psip_port= &psip_port_table[port];
266
267 if (!(psip_port->pp_flags & PPF_ENABLED))
268 return ENXIO;
269
270 for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
271 {
272 if (psip_fd->pf_flags & PFF_INUSE)
273 continue;
274 break;
275 }
276 if (i == PSIP_FD_NR)
277 return ENFILE;
278 psip_fd->pf_flags |= PFF_INUSE;
279 psip_fd->pf_srfd= srfd;
280 psip_fd->pf_port= psip_port;
281 psip_fd->pf_get_userdata= get_userdata;
282 psip_fd->pf_put_userdata= put_userdata;
283 psip_port->pp_opencnt++;
284
285 return i;
286}
287
288PRIVATE int psip_ioctl(fd, req)
289int fd;
290ioreq_t req;
291{
292 int result;
293 psip_fd_t *psip_fd;
294 acc_t *data;
295 nwio_ipconf_t *ipconfp;
296 nwio_psipopt_t *psip_opt, *newoptp;
297
298 assert(fd >= 0 && fd < PSIP_FD_NR);
299 psip_fd= &psip_fd_table[fd];
300
301 switch(req)
302 {
303 case NWIOSIPCONF:
304 data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0,
305 sizeof(*ipconfp), TRUE);
306 if (!data)
307 {
308 result= EFAULT;
309 break;
310 }
311 data= bf_packIffLess(data, sizeof(*ipconfp));
312 assert (data->acc_length == sizeof(*ipconfp));
313
314 ipconfp= (nwio_ipconf_t *)ptr2acc_data(data);
315 result= ip_setconf(psip_fd->pf_port->pp_ipdev, ipconfp);
316 bf_afree(data);
317 reply_thr_get(psip_fd, result, TRUE);
318 break;
319 case NWIOSPSIPOPT:
320 data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0,
321 sizeof(*psip_opt), TRUE);
322 if (!data)
323 {
324 result= EFAULT;
325 break;
326 }
327 data= bf_packIffLess(data, sizeof(*psip_opt));
328 assert (data->acc_length == sizeof(*psip_opt));
329
330 newoptp= (nwio_psipopt_t *)ptr2acc_data(data);
331 result= psip_setopt(psip_fd, newoptp);
332 bf_afree(data);
333 if (result == NW_OK)
334 {
335 if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_PROMISC)
336 {
337 psip_fd->pf_flags |= PFF_PROMISC;
338 psip_fd->pf_port->pp_flags |= PPF_PROMISC;
339 }
340 else
341 {
342 psip_fd->pf_flags &= ~PFF_PROMISC;
343 check_promisc(psip_fd->pf_port);
344 }
345 if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_NEXTHOP)
346 {
347 psip_fd->pf_flags |= PFF_NEXTHOP;
348 }
349 else
350 {
351 psip_fd->pf_flags &= ~PFF_NEXTHOP;
352 }
353 }
354 reply_thr_get(psip_fd, result, TRUE);
355 break;
356 case NWIOGPSIPOPT:
357 data= bf_memreq(sizeof(*psip_opt));
358 psip_opt= (nwio_psipopt_t *)ptr2acc_data(data);
359
360 *psip_opt= psip_fd->pf_psipopt;
361 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 0,
362 data, TRUE);
363 if (result == NW_OK)
364 reply_thr_put(psip_fd, NW_OK, TRUE);
365 break;
366 default:
367 reply_thr_put(psip_fd, ENOTTY, TRUE);
368 break;
369 }
370 return NW_OK;
371}
372
373PRIVATE int psip_read(fd, count)
374int fd;
375size_t count;
376{
377 psip_port_t *psip_port;
378 psip_fd_t *psip_fd;
379 acc_t *pack;
380 size_t buf_size;
381 int result, result1;
382
383 assert(fd >= 0 && fd < PSIP_FD_NR);
384 psip_fd= &psip_fd_table[fd];
385 psip_port= psip_fd->pf_port;
386
387 if ((psip_fd->pf_flags & PFF_PROMISC) && psip_port->pp_promisc_head)
388 {
389 /* Deliver a queued packet. */
390 pack= psip_port->pp_promisc_head;
391 buf_size= bf_bufsize(pack);
392 if (buf_size <= count)
393 {
394 psip_port->pp_promisc_head= pack->acc_ext_link;
395 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
396 (size_t)0, pack, FALSE);
397 if (result == NW_OK)
398 result= buf_size;
399 }
400 else
401 result= EPACKSIZE;
402
403 result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
404 (size_t)result, NULL, FALSE);
405 assert(result1 == NW_OK);
406 return NW_OK;
407 }
408
409 psip_fd->pf_rd_count= count;
410 if (psip_port->pp_rd_head == NULL)
411 psip_port->pp_rd_head= psip_fd;
412 else
413 psip_port->pp_rd_tail->pf_rd_next= psip_fd;
414 psip_fd->pf_rd_next= NULL;
415 psip_port->pp_rd_tail= psip_fd;
416
417 psip_fd->pf_flags |= PFF_READ_IP;
418 if (!(psip_fd->pf_flags & PFF_PROMISC))
419 ipps_get(psip_port->pp_ipdev);
420 if (psip_fd->pf_flags & PFF_READ_IP)
421 return NW_SUSPEND;
422 return NW_OK;
423}
424
425PRIVATE int psip_write(fd, count)
426int fd;
427size_t count;
428{
429 psip_port_t *psip_port;
430 psip_fd_t *psip_fd;
431 acc_t *pack, *hdr_pack;
432 psip_io_hdr_t *hdr;
433 size_t pack_len;
434 ipaddr_t nexthop;
435
436 assert(fd >= 0 && fd < PSIP_FD_NR);
437 psip_fd= &psip_fd_table[fd];
438 psip_port= psip_fd->pf_port;
439
440 pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)0,
441 count, FALSE);
442 if (pack == NULL)
443 {
444 pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd,
445 (size_t)EFAULT, (size_t)0, FALSE);
446 assert(pack == NULL);
447 return NW_OK;
448 }
449
450 if (psip_fd->pf_flags & PFF_NEXTHOP)
451 {
452 pack_len= bf_bufsize(pack);
453 if (pack_len <= sizeof(nexthop))
454 {
455 /* Something strange */
456 bf_afree(pack); pack= NULL;
457 pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd,
458 (size_t)EPACKSIZE, (size_t)0, FALSE);
459 assert(pack == NULL);
460 return NW_OK;
461 }
462 pack= bf_packIffLess(pack, sizeof(nexthop));
463 nexthop= *(ipaddr_t *)ptr2acc_data(pack);
464 pack= bf_delhead(pack, sizeof(nexthop));
465
466 /* Map multicast to broadcast */
467 if ((nexthop & HTONL(0xE0000000)) == HTONL(0xE0000000))
468 nexthop= HTONL(0xffffffff);
469 }
470 else
471 {
472 /* Assume point to point */
473 nexthop= HTONL(0x00000000);
474 }
475
476 if (psip_port->pp_flags & PPF_PROMISC)
477 {
478 /* Deal with promiscuous mode. */
479 hdr_pack= bf_memreq(sizeof(*hdr));
480 hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
481 memset(hdr, '\0', sizeof(*hdr));
482 hdr->pih_flags |= PF_REM2LOC;
483 hdr->pih_nexthop= nexthop;
484
485 pack->acc_linkC++;
486 hdr_pack->acc_next= pack;
487 hdr_pack->acc_ext_link= NULL;
488 if (psip_port->pp_promisc_head)
489 {
490 /* Append at the end. */
491 psip_port->pp_promisc_tail->acc_ext_link= hdr_pack;
492 psip_port->pp_promisc_tail= hdr_pack;
493 }
494 else
495 {
496 /* First packet. */
497 psip_port->pp_promisc_head= hdr_pack;
498 psip_port->pp_promisc_tail= hdr_pack;
499 if (psip_port->pp_rd_head)
500 promisc_restart_read(psip_port);
501 }
502 }
503 ipps_put(psip_port->pp_ipdev, nexthop, pack);
504 pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)count,
505 (size_t)0, FALSE);
506 assert(pack == NULL);
507 return NW_OK;
508}
509
510PRIVATE int psip_select(fd, operations)
511int fd;
512unsigned operations;
513{
514 printf("psip_select: not implemented\n");
515 return 0;
516}
517
518PRIVATE void psip_close(fd)
519int fd;
520{
521 psip_port_t *psip_port;
522 psip_fd_t *psip_fd;
523
524 assert(fd >= 0 && fd < PSIP_FD_NR);
525 psip_fd= &psip_fd_table[fd];
526 psip_port= psip_fd->pf_port;
527
528 if (psip_fd->pf_flags & PFF_PROMISC)
529 {
530 /* Check if the port should still be in promiscuous mode.
531 */
532 psip_fd->pf_flags &= ~PFF_PROMISC;
533 check_promisc(psip_fd->pf_port);
534 }
535
536 assert(psip_port->pp_opencnt >0);
537 psip_port->pp_opencnt--;
538 psip_fd->pf_flags= PFF_EMPTY;
539 ipps_get(psip_port->pp_ipdev);
540
541}
542
543PRIVATE int psip_cancel(fd, which_operation)
544int fd;
545int which_operation;
546{
547 psip_port_t *psip_port;
548 psip_fd_t *psip_fd, *prev_fd, *tmp_fd;
549 int result;
550
551 DBLOCK(1, printf("psip_cancel(%d, %d)\n", fd, which_operation));
552
553 assert(fd >= 0 && fd < PSIP_FD_NR);
554 psip_fd= &psip_fd_table[fd];
555 psip_port= psip_fd->pf_port;
556
557 switch(which_operation)
558 {
559 case SR_CANCEL_IOCTL:
560 ip_panic(( "should not be here" ));
561 case SR_CANCEL_READ:
562 assert(psip_fd->pf_flags & PFF_READ_IP);
563 for (prev_fd= NULL, tmp_fd= psip_port->pp_rd_head; tmp_fd;
564 prev_fd= tmp_fd, tmp_fd= tmp_fd->pf_rd_next)
565 {
566 if (tmp_fd == psip_fd)
567 break;
568 }
569 if (tmp_fd == NULL)
570 ip_panic(( "unable to find to request to cancel" ));
571 if (prev_fd == NULL)
572 psip_port->pp_rd_head= psip_fd->pf_rd_next;
573 else
574 prev_fd->pf_rd_next= psip_fd->pf_rd_next;
575 if (psip_fd->pf_rd_next == NULL)
576 psip_port->pp_rd_tail= prev_fd;
577 psip_fd->pf_flags &= ~PFF_READ_IP;
578 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
579 (size_t)EINTR, NULL, FALSE);
580 assert(result == NW_OK);
581 break;
582 case SR_CANCEL_WRITE:
583 ip_panic(( "should not be here" ));
584 default:
585 ip_panic(( "invalid operation for cancel" ));
586 }
587 return NW_OK;
588}
589
590PRIVATE void promisc_restart_read(psip_port)
591psip_port_t *psip_port;
592{
593 psip_fd_t *psip_fd, *prev, *next;
594 acc_t *pack;
595 size_t buf_size;
596 int result, result1;
597
598 /* Overkill at the moment: just one reader in promiscious mode is
599 * allowed.
600 */
601 pack= psip_port->pp_promisc_head;
602 if (!pack)
603 return;
604 assert(pack->acc_ext_link == NULL);
605
606 for(psip_fd= psip_port->pp_rd_head, prev= NULL; psip_fd;
607 prev= psip_fd, psip_fd= psip_fd->pf_rd_next)
608 {
609again:
610 if (!(psip_fd->pf_flags & PFF_PROMISC))
611 continue;
612 next= psip_fd->pf_rd_next;
613 if (prev)
614 prev->pf_rd_next= next;
615 else
616 psip_port->pp_rd_head= next;
617 if (!next)
618 psip_port->pp_rd_tail= prev;
619
620 assert(psip_fd->pf_flags & PFF_READ_IP);
621 psip_fd->pf_flags &= ~PFF_READ_IP;
622
623 buf_size= bf_bufsize(pack);
624 if (buf_size <= psip_fd->pf_rd_count)
625 {
626 psip_port->pp_promisc_head= pack->acc_ext_link;
627 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
628 (size_t)0, pack, FALSE);
629 if (result == NW_OK)
630 result= buf_size;
631 }
632 else
633 result= EPACKSIZE;
634
635 result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
636 (size_t)result, NULL, FALSE);
637 assert(result1 == NW_OK);
638
639 if (psip_port->pp_promisc_head)
640 {
641 /* Restart from the beginning */
642 assert(result == EPACKSIZE);
643 psip_fd= psip_port->pp_rd_head;
644 prev= NULL;
645 goto again;
646 }
647 break;
648 }
649}
650
651PRIVATE int psip_setopt(psip_fd, newoptp)
652psip_fd_t *psip_fd;
653nwio_psipopt_t *newoptp;
654{
655 nwio_psipopt_t oldopt;
656 unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags;
657 unsigned long new_flags;
658
659 oldopt= psip_fd->pf_psipopt;
660
661 old_en_flags= oldopt.nwpo_flags & 0xffff;
662 old_di_flags= (oldopt.nwpo_flags >> 16) & 0xffff;
663
664 new_en_flags= newoptp->nwpo_flags & 0xffff;
665 new_di_flags= (newoptp->nwpo_flags >> 16) & 0xffff;
666
667 if (new_en_flags & new_di_flags)
668 return EBADMODE;
669
670 /* NWUO_LOCADDR_MASK */
671 if (!((new_en_flags | new_di_flags) & NWPO_PROMISC_MASK))
672 {
673 new_en_flags |= (old_en_flags & NWPO_PROMISC_MASK);
674 new_di_flags |= (old_di_flags & NWPO_PROMISC_MASK);
675 }
676
677 new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
678 if ((new_flags & NWPO_EN_PROMISC) &&
679 (psip_fd->pf_port->pp_flags & PPF_PROMISC))
680 {
681 printf("psip_setopt: EBUSY for port %d, flags 0x%x\n",
682 psip_fd->pf_port - psip_port_table,
683 psip_fd->pf_port->pp_flags);
684 /* We can support only one at a time. */
685 return EBUSY;
686 }
687
688 psip_fd->pf_psipopt= *newoptp;
689 psip_fd->pf_psipopt.nwpo_flags= new_flags;
690
691 return NW_OK;
692}
693
694PRIVATE void check_promisc(psip_port)
695psip_port_t *psip_port;
696{
697 int i;
698 psip_fd_t *psip_fd;
699 acc_t *acc, *acc_next;
700
701 /* Check if the port should still be in promiscuous mode. Overkill
702 * at the moment.
703 */
704 if (!(psip_port->pp_flags & PPF_PROMISC))
705 return;
706
707 psip_port->pp_flags &= ~PPF_PROMISC;
708 for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
709 {
710 if ((psip_fd->pf_flags & (PFF_INUSE|PFF_PROMISC)) !=
711 (PFF_INUSE|PFF_PROMISC))
712 {
713 continue;
714 }
715 if (psip_fd->pf_port != psip_port)
716 continue;
717 printf("check_promisc: setting PROMISC for port %d\n",
718 psip_port-psip_port_table);
719 psip_port->pp_flags |= PPF_PROMISC;
720 break;
721 }
722 if (!(psip_port->pp_flags & PPF_PROMISC))
723 {
724 /* Delete queued packets. */
725 acc= psip_port->pp_promisc_head;
726 psip_port->pp_promisc_head= NULL;
727 while (acc)
728 {
729 acc_next= acc->acc_ext_link;
730 bf_afree(acc);
731 acc= acc_next;
732 }
733 }
734}
735
736PRIVATE void psip_buffree (priority)
737int priority;
738{
739 int i;
740 psip_port_t *psip_port;
741 acc_t *tmp_acc, *next_acc;
742
743 if (priority == PSIP_PRI_EXP_PROMISC)
744 {
745 for (i=0, psip_port= psip_port_table; i<psip_conf_nr;
746 i++, psip_port++)
747 {
748 if (!(psip_port->pp_flags & PPF_CONFIGURED) )
749 continue;
750 if (psip_port->pp_promisc_head)
751 {
752 tmp_acc= psip_port->pp_promisc_head;
753 while(tmp_acc)
754 {
755 next_acc= tmp_acc->acc_ext_link;
756 bf_afree(tmp_acc);
757 tmp_acc= next_acc;
758 }
759 psip_port->pp_promisc_head= NULL;
760 }
761 }
762 }
763}
764
765#ifdef BUF_CONSISTENCY_CHECK
766PRIVATE void psip_bufcheck()
767{
768 int i;
769 psip_port_t *psip_port;
770 acc_t *tmp_acc;
771
772 for (i= 0, psip_port= psip_port_table; i<psip_conf_nr;
773 i++, psip_port++)
774 {
775 for (tmp_acc= psip_port->pp_promisc_head; tmp_acc;
776 tmp_acc= tmp_acc->acc_ext_link)
777 {
778 bf_check_acc(tmp_acc);
779 }
780 }
781}
782#endif
783
784/*
785reply_thr_put
786*/
787
788PRIVATE void reply_thr_put(psip_fd, reply, for_ioctl)
789psip_fd_t *psip_fd;
790int reply;
791int for_ioctl;
792{
793 int result;
794
795 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, reply,
796 (acc_t *)0, for_ioctl);
797 assert(result == NW_OK);
798}
799
800/*
801reply_thr_get
802*/
803
804PRIVATE void reply_thr_get(psip_fd, reply, for_ioctl)
805psip_fd_t *psip_fd;
806int reply;
807int for_ioctl;
808{
809 acc_t *result;
810 result= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, reply,
811 (size_t)0, for_ioctl);
812 assert (!result);
813}
814
815
816/*
817 * $PchId: psip.c,v 1.15 2005/06/28 14:19:29 philip Exp $
818 */
Note: See TracBrowser for help on using the repository browser.