1 /* WIREFILTER (C) 2005 Renzo Davoli
2 * Licensed under the GPLv2
3 * Modified by Ludovico Gardenghi 2005
5 * This filter can be used for testing network protcols.
6 * It is possible to loose, delay or reorder packets.
7 * Options can be set on command line or interactively with a remote interface
8 * on a unix socket (see unixterm).
24 #include <sys/types.h>
26 #include <sys/socket.h>
34 static int alternate_stdin
;
35 static int alternate_stdout
;
36 #define NPFD NPIPES+MAXCONN+1
37 struct pollfd pfd
[NPFD
];
44 double loss
[2],lossplus
[2];
45 double delay
[2],delayplus
[2];
46 double ddup
[2],ddupplus
[2];
47 double band
[2],bandplus
[2];
48 double speed
[2],speedplus
[2];
49 double capacity
[2],capacityplus
[2];
50 double noise
[2],noiseplus
[2];
51 double mtu
[2],mtuplus
[2];
52 struct timeval nextband
[2];
53 struct timeval nextspeed
[2];
60 #define MGMTMODEARG 129
65 static void readdualvalue(char *s
,double *val
,double *valplus
)
72 while ((s
[n
] == ' ' || s
[n
] == '\n' || s
[n
] == '\t') && n
>0)
94 if ((n
=sscanf(s
,"%lf+%lf",&v
,&vplus
)) > 0) {
95 val
[LR
]=val
[RL
]=v
*mult
;
96 valplus
[LR
]=valplus
[RL
]=vplus
*mult
;
97 } else if ((n
=sscanf(s
,"LR%lf+%lf",&v
,&vplus
)) > 0) {
99 valplus
[LR
]=vplus
*mult
;
100 } else if ((n
=sscanf(s
,"RL%lf+%lf",&v
,&vplus
)) > 0) {
102 valplus
[RL
]=vplus
*mult
;
107 unsigned long long when
;
114 struct packpq sentinel
={0,0,NULL
,0};
116 unsigned long long maxwhen
;
125 gettimeofday(&v
,NULL
);
126 deltat
=pqh
[1]->when
-(v
.tv_sec
*1000000+v
.tv_usec
);
127 return (deltat
>0)?(int)(deltat
/1000):0;
132 int writepacket(int dir
,const unsigned char *buf
,int size
)
135 if (noise
[dir
]+noiseplus
[dir
] > 0) {
136 double noiseval
=noise
[dir
];
138 if (noiseplus
) noiseval
+=((drand48()*2.0)-1.0)*noiseplus
[dir
];
139 while ((drand48()*8*MEGA
) < (size
-2)*8*noiseval
)
142 unsigned char noisedpacket
[BUFSIZE
];
143 memcpy(noisedpacket
,buf
,size
);
145 int flippedbit
=(drand48()*size
*8);
146 noisedpacket
[(flippedbit
>> 3) + 2] ^= 1<<(flippedbit
& 0x7);
149 return write(outfd
[dir
],noisedpacket
,size
);
151 return write(outfd
[dir
],buf
,size
);
153 return write(outfd
[dir
],buf
,size
);
156 /* packet queues are priority queues implemented on a heap.
157 * enqueue time = dequeue time = O(log n) max&mean
160 static void packet_dequeue()
163 gettimeofday(&v
,NULL
);
164 unsigned long long now
=v
.tv_sec
*1000000+v
.tv_usec
;
165 while (npq
>0 && pqh
[1]->when
<= now
) {
166 struct packpq
*old
=pqh
[npq
--];
168 bufsize
[pqh
[1]->dir
] -= pqh
[1]->size
;
169 writepacket(pqh
[1]->dir
,pqh
[1]->buf
,pqh
[1]->size
);
175 if (j
<npq
&& pqh
[j
]->when
> pqh
[j
+1]->when
) j
++;
176 if (old
->when
<= pqh
[j
]->when
) {
186 static void packet_enqueue(int dir
,const unsigned char *buf
,int size
,int delms
)
191 if (capacity
[dir
]+capacityplus
[dir
] > 0) {
192 double capval
=capacity
[dir
];
193 if (capacityplus
[dir
])
194 capval
+=((drand48()*2.0)-1.0)*capacityplus
[dir
];
195 if ((bufsize
[dir
]+size
) > capval
)
200 struct packpq
*new=malloc(sizeof(struct packpq
));
202 fprintf(stderr
,"%s: malloc elem %s\n",progname
,strerror(errno
));
205 gettimeofday(&v
,NULL
);
206 new->when
=v
.tv_sec
* 1000000 + v
.tv_usec
+ delms
* 1000;
207 if (new->when
> maxwhen
) maxwhen
=new->when
;
208 if (!nofifo
&& new->when
< maxwhen
) new->when
=maxwhen
;
210 new->buf
=malloc(size
);
211 if (new->buf
==NULL
) {
212 fprintf(stderr
,"%s: malloc elem buf %s\n",progname
,strerror(errno
));
215 memcpy(new->buf
,buf
,size
);
219 pqh
=malloc(PQCHUNK
*sizeof(struct packpq
*));
221 fprintf(stderr
,"%s: malloc %s\n",progname
,strerror(errno
));
224 pqh
[0]=&sentinel
; maxpq
=PQCHUNK
;
227 pqh
=realloc(pqh
,(maxpq
=maxpq
+PQCHUNK
) * sizeof(struct packpq
*));
229 fprintf(stderr
,"%s: malloc %s\n",progname
,strerror(errno
));
234 while (new->when
< pqh
[k
>>1]->when
) {
242 void handle_packet(int dir
,const unsigned char *buf
,int size
)
245 if (mtu
[dir
] > 0 && size
> mtu
[dir
])
249 if (loss
[dir
]-lossplus
[dir
] >= 100.0)
251 if (loss
[dir
]+lossplus
[dir
] > 0) {
252 double losval
=(loss
[dir
]+((drand48()*2.0)-1.0)*lossplus
[dir
])/100;
253 if (drand48() < losval
)
259 if (ddup
[dir
]+ddupplus
[dir
] > 0) {
260 double dupval
=(ddup
[dir
]+((drand48()*2.0)-1.0)*ddupplus
[dir
])/100;
261 while (drand48() < dupval
)
268 if (speed
[dir
]+speedplus
[dir
] > 0) {
269 double speedval
=speed
[dir
];
270 if (speedplus
[dir
]) {
271 speedval
+=((drand48()*2.0)-1.0)*speedplus
[dir
];
272 if (speedval
<=0) return;
275 unsigned int commtime
=((unsigned)size
)*1000000/((unsigned int)speedval
);
277 gettimeofday(&tv
,NULL
);
278 banddelay
=commtime
/1000;
279 if (timercmp(&tv
,&nextspeed
[dir
], > ))
281 nextspeed
[dir
].tv_usec
+= commtime
;
282 nextspeed
[dir
].tv_sec
+= nextspeed
[dir
].tv_usec
/ 1000000;
283 nextspeed
[dir
].tv_usec
%= 1000000;
288 if (band
[dir
]+bandplus
[dir
] > 0) {
289 double bandval
=band
[dir
];
291 bandval
+=((drand48()*2.0)-1.0)*bandplus
[dir
];
292 if (bandval
<=0) return;
295 unsigned int commtime
=((unsigned)size
)*1000000/((unsigned int)bandval
);
297 gettimeofday(&tv
,NULL
);
298 if (timercmp(&tv
,&nextband
[dir
], > )) {
300 banddelay
=commtime
/1000;
302 timersub(&nextband
[dir
],&tv
,&tv
);
303 banddelay
=tv
.tv_sec
*1000 + (tv
.tv_usec
+ commtime
)/1000;
305 nextband
[dir
].tv_usec
+= commtime
;
306 nextband
[dir
].tv_sec
+= nextband
[dir
].tv_usec
/ 1000000;
307 nextband
[dir
].tv_usec
%= 1000000;
313 if (banddelay
>= 0) {
314 if (banddelay
> 0 || delay
[dir
]+delayplus
[dir
] > 0) {
315 double delval
=(delay
[dir
]+((drand48()*2.0)-1.0)*delayplus
[dir
]);
316 delval
=(delval
>= 0)?delval
+banddelay
:banddelay
;
318 packet_enqueue(dir
,buf
,size
,(int) delval
);
320 writepacket(dir
,buf
,size
);
322 writepacket(dir
,buf
,size
);
328 #define MIN(X,Y) (((X)<(Y))?(X):(Y))
330 static void splitpacket(const unsigned char *buf
,int size
,int dir
)
332 static unsigned char fragment
[BUFSIZE
][2];
333 static unsigned char *fragp
[2];
334 static unsigned int rnx
[2],remaining
[2];
336 //fprintf(stderr,"%s: splitpacket rnx=%d remaining=%d size=%d\n",progname,rnx[dir],remaining[dir],size);
339 register int amount
=MIN(remaining
[dir
],size
);
340 //fprintf(stderr,"%s: fragment amount %d\n",progname,amount);
341 memcpy(fragp
[dir
],buf
,amount
);
342 remaining
[dir
]-=amount
;
346 if (remaining
[dir
]==0) {
347 //fprintf(stderr,"%s: delivered defrag %d\n",progname,rnx[dir]);
348 handle_packet(dir
,fragment
[dir
],rnx
[dir
]+2);
353 rnx
[dir
]=(buf
[0]<<8)+buf
[1];
354 //fprintf(stderr,"%s: packet %d size %d %x %x dir %d\n",progname,rnx[dir],size-2,buf[0],buf[1],dir);
356 fprintf(stderr
,"%s: Packet length error size %d rnx %d\n",progname
,size
,rnx
[dir
]);
360 if (rnx
[dir
]+2 > size
) {
361 //fprintf(stderr,"%s: begin defrag %d\n",progname,rnx[dir]);
362 fragp
[dir
]=fragment
[dir
];
363 memcpy(fragp
[dir
],buf
,size
);
364 remaining
[dir
]=rnx
[dir
]+2-size
;
368 handle_packet(dir
,buf
,rnx
[dir
]+2);
376 static void packet_in(int dir
)
378 unsigned char buf
[BUFSIZE
];
380 n
=read(pfd
[dir
].fd
,buf
,BUFSIZE
);
383 splitpacket(buf
,n
,dir
);
386 static void initrand()
389 gettimeofday(&v
,NULL
);
390 srand48(v
.tv_sec
^ v
.tv_usec
^ getpid());
393 static int check_open_fifos(struct pollfd
*pfd
,int *outfd
)
396 struct stat stfd
[NPIPES
];
399 env_in
=getenv("ALTERNATE_STDIN");
400 env_out
=getenv("ALTERNATE_STDOUT");
402 alternate_stdin
=atoi(env_in
);
404 alternate_stdout
=atoi(env_out
);
405 if (fstat(STDIN_FILENO
,&stfd
[STDIN_FILENO
]) < 0) {
406 fprintf(stderr
,"%s: Error on stdin: %s\n",progname
,strerror(errno
));
409 if (fstat(STDOUT_FILENO
,&stfd
[STDOUT_FILENO
]) < 0) {
410 fprintf(stderr
,"%s: Error on stdout: %s\n",progname
,strerror(errno
));
413 if (!S_ISFIFO(stfd
[STDIN_FILENO
].st_mode
)) {
414 fprintf(stderr
,"%s: Error on stdin: %s\n",progname
,"it is not a pipe");
417 if (!S_ISFIFO(stfd
[STDOUT_FILENO
].st_mode
)) {
418 fprintf(stderr
,"%s: Error on stdin: %s\n",progname
,"it is not a pipe");
421 if (env_in
== NULL
|| fstat(alternate_stdin
,&stfd
[0]) < 0) {
423 pfd
[0].fd
=STDIN_FILENO
;
424 pfd
[0].events
=POLLIN
| POLLHUP
;
426 outfd
[0]=STDOUT_FILENO
;
428 if (fstat(outfd
[1],&stfd
[1]) < 0) {
429 fprintf(stderr
,"%s: Error on secondary out: %s\n",progname
,strerror(errno
));
432 if (!S_ISFIFO(stfd
[0].st_mode
)) {
433 fprintf(stderr
,"%s: Error on secondary in: %s\n",progname
,"it is not a pipe");
436 if (!S_ISFIFO(stfd
[1].st_mode
)) {
437 fprintf(stderr
,"%s: Error on secondary out: %s\n",progname
,"it is not a pipe");
441 pfd
[LR
].fd
=STDIN_FILENO
;
442 pfd
[LR
].events
=POLLIN
| POLLHUP
;
444 outfd
[LR
]=alternate_stdout
;
445 pfd
[RL
].fd
=alternate_stdin
;
446 pfd
[RL
].events
=POLLIN
| POLLHUP
;
448 outfd
[RL
]=STDOUT_FILENO
;
453 static void cleanup(void)
459 static void sig_handler(int sig
)
461 /*fprintf(stderr,"Caught signal %d, cleaning up and exiting", sig);*/
463 signal(sig
, SIG_DFL
);
467 static void setsighandlers()
469 /* setting signal handlers.
470 * * * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
471 * * * ignores all the others signals which could cause termination. */
472 struct { int sig
; const char *name
; int ignore
; } signals
[] = {
473 { SIGHUP
, "SIGHUP", 0 },
474 { SIGINT
, "SIGINT", 0 },
475 { SIGPIPE
, "SIGPIPE", 1 },
476 { SIGALRM
, "SIGALRM", 1 },
477 { SIGTERM
, "SIGTERM", 0 },
478 { SIGUSR1
, "SIGUSR1", 1 },
479 { SIGUSR2
, "SIGUSR2", 1 },
480 { SIGPROF
, "SIGPROF", 1 },
481 { SIGVTALRM
, "SIGVTALRM", 1 },
483 { SIGPOLL
, "SIGPOLL", 1 },
484 { SIGSTKFLT
, "SIGSTKFLT", 1 },
485 { SIGIO
, "SIGIO", 1 },
486 { SIGPWR
, "SIGPWR", 1 },
487 { SIGUNUSED
, "SIGUNUSED", 1 },
490 { SIGXCPU
, "SIGXCPU", 1 },
491 { SIGXFSZ
, "SIGXFSZ", 1 },
497 for(i
= 0; signals
[i
].sig
!= 0; i
++)
498 if(signal(signals
[i
].sig
,
499 signals
[i
].ignore
? SIG_IGN
: sig_handler
) < 0)
500 fprintf(stderr
,"%s: Setting handler for %s: %s", progname
, signals
[i
].name
,
504 static int openmgmt(char *mgmt
)
507 struct sockaddr_un sun
;
510 if((mgmtconnfd
= socket(PF_UNIX
, SOCK_STREAM
, 0)) < 0){
511 fprintf(stderr
,"%s: mgmt socket: %s",progname
,strerror(errno
));
514 if(setsockopt(mgmtconnfd
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &one
,
516 fprintf(stderr
,"%s: mgmt setsockopt: %s",progname
,strerror(errno
));
519 if(fcntl(mgmtconnfd
, F_SETFL
, O_NONBLOCK
) < 0){
520 fprintf(stderr
,"%s: Setting O_NONBLOCK on mgmt fd: %s",progname
,strerror(errno
));
523 sun
.sun_family
= PF_UNIX
;
524 snprintf(sun
.sun_path
,sizeof(sun
.sun_path
),"%s",mgmt
);
525 if(bind(mgmtconnfd
, (struct sockaddr
*) &sun
, sizeof(sun
)) < 0){
526 fprintf(stderr
,"%s: mgmt bind %s",progname
,strerror(errno
));
529 chmod(sun
.sun_path
,mgmtmode
);
530 if(listen(mgmtconnfd
, 15) < 0){
531 fprintf(stderr
,"%s: mgmt listen: %s",progname
,strerror(errno
));
537 static char header
[]="\nVDE wirefilter V.%s\n(C) R.Davoli 2005,2006 - GPLv2\n";
538 static char prompt
[]="\nVDEwf:";
539 static int newmgmtconn(int fd
,struct pollfd
*pfd
,int nfds
)
544 struct sockaddr addr
;
545 new = accept(fd
, &addr
, &len
);
547 fprintf(stderr
,"%s: mgmt accept %s",progname
,strerror(errno
));
551 snprintf(buf
,MAXCMD
,header
,PACKAGE_VERSION
);
552 write(new,buf
,strlen(buf
));
553 write(new,prompt
,strlen(prompt
));
555 pfd
[nfds
].events
=POLLIN
| POLLHUP
;
559 fprintf(stderr
,"%s: too many mgmt connections",progname
);
565 static void printoutc(int fd
, const char *format
, ...)
568 char outbuf
[MAXCMD
+1];
570 va_start (arg
, format
);
571 vsnprintf(outbuf
,MAXCMD
,format
,arg
);
573 write(fd
,outbuf
,strlen(outbuf
));
576 static int setdelay(int fd
,char *s
)
578 readdualvalue(s
,delay
,delayplus
);
582 static int setloss(int fd
,char *s
)
584 readdualvalue(s
,loss
,lossplus
);
588 static int setddup(int fd
,char *s
)
590 readdualvalue(s
,ddup
,ddupplus
);
594 static int setband(int fd
,char *s
)
596 readdualvalue(s
,band
,bandplus
);
600 static int setnoise(int fd
,char *s
)
602 readdualvalue(s
,noise
,noiseplus
);
606 static int setmtu(int fd
,char *s
)
608 readdualvalue(s
,mtu
,mtuplus
);
612 static int setspeed(int fd
,char *s
)
614 readdualvalue(s
,speed
,speedplus
);
618 static int setcapacity(int fd
,char *s
)
620 readdualvalue(s
,capacity
,capacityplus
);
624 static int setfifo(int fd
,char *s
)
634 static int logout(int fd
,char *s
)
639 static int doshutdown(int fd
,char *s
)
645 static int help(int fd
,char *s
)
647 printoutc(fd
, "help: print a summary of mgmt commands");
648 printoutc(fd
, "showinfo: show status and parameter values");
649 printoutc(fd
, "loss: set loss percentage");
650 printoutc(fd
, "delay: set delay ms");
651 printoutc(fd
, "dup: set dup packet percentage");
652 printoutc(fd
, "bandwidth: set channel bandwidth bytes/sec");
653 printoutc(fd
, "speed: set interface speed bytes/sec");
654 printoutc(fd
, "noise: set noise factor bits/Mbyte");
655 printoutc(fd
, "mtu: set channel MTU (bytes)");
656 printoutc(fd
, "capacity: set channel capacity (bytes)");
657 printoutc(fd
, "fifo: set channel fifoness");
658 printoutc(fd
, "shutdown: shut the channel down");
659 printoutc(fd
, "logout: log out from this mgmt session");
663 static int showinfo(int fd
,char *s
)
665 printoutc(fd
, "WireFilter: %sdirectional",(ndirs
==2)?"bi":"mono");
667 printoutc(fd
, "Loss L->R %g+%g R->L %g+%g",loss
[LR
],lossplus
[LR
],loss
[RL
],lossplus
[RL
]);
668 printoutc(fd
, "Delay L->R %g+%g R->L %g+%g",delay
[LR
],delayplus
[LR
],delay
[RL
],delayplus
[RL
]);
669 printoutc(fd
, "Dup L->R %g+%g R->L %g+%g",ddup
[LR
],ddupplus
[LR
],ddup
[RL
],ddupplus
[RL
]);
670 printoutc(fd
, "Bandw L->R %g+%g R->L %g+%g",band
[LR
],bandplus
[LR
],band
[RL
],bandplus
[RL
]);
671 printoutc(fd
, "Speed L->R %g+%g R->L %g+%g",speed
[LR
],speedplus
[LR
],speed
[RL
],speedplus
[RL
]);
672 printoutc(fd
, "Noise L->R %g+%g R->L %g+%g",noise
[LR
],noiseplus
[LR
],noise
[RL
],noiseplus
[RL
]);
673 printoutc(fd
, "MTU L->R %g R->L %g ",mtu
[LR
],mtu
[RL
]);
674 printoutc(fd
, "Cap. L->R %g+%g R->L %g+%g",capacity
[LR
],capacityplus
[LR
],capacity
[RL
],capacityplus
[RL
]);
675 printoutc(fd
, "Current Delay Queue size: L->R %d R->L %d ",bufsize
[LR
],bufsize
[RL
]);
677 printoutc(fd
, "Loss %g+%g",loss
[0],lossplus
[0]);
678 printoutc(fd
, "Delay %g+%g",delay
[0],delayplus
[0]);
679 printoutc(fd
, "Dup %g+%g",ddup
[0],ddupplus
[0]);
680 printoutc(fd
, "Bandw %g+%g",band
[0],bandplus
[0]);
681 printoutc(fd
, "Speed %g+%g",speed
[0],speedplus
[0]);
682 printoutc(fd
, "Noise %g+%g",noise
[0],noiseplus
[0]);
683 printoutc(fd
, "MTU %g",mtu
[0]);
684 printoutc(fd
, "Cap. %g+%g",capacity
[0],capacityplus
[0]);
685 printoutc(fd
, "Current Delay Queue size: %d",bufsize
[0]);
687 printoutc(fd
,"Fifoness %s",(nofifo
== 0)?"TRUE":"FALSE");
688 printoutc(fd
,"Waiting packets in delay queues %d",npq
);
692 static struct comlist
{
694 int (*fun
)(int fd
,char *arg
);
697 {"showinfo",showinfo
},
701 {"bandwidth",setband
},
704 {"capacity",setcapacity
},
709 {"shutdown",doshutdown
}
712 #define NCL sizeof(commandlist)/sizeof(struct comlist)
714 static int handle_cmd(int fd
,char *inbuf
)
718 while (*inbuf
== ' ' || *inbuf
== '\t') inbuf
++;
719 if (*inbuf
!= '\0' && *inbuf
!= '#') {
721 && strncmp(commandlist
[i
].tag
,inbuf
,strlen(commandlist
[i
].tag
))!=0;
726 inbuf
+= strlen(commandlist
[i
].tag
);
727 while (*inbuf
== ' ' || *inbuf
== '\t') inbuf
++;
728 rv
=commandlist
[i
].fun(fd
,inbuf
);
730 printoutc(fd
,"1%03d %s",rv
,strerror(rv
));
736 static int mgmtcommand(int fd
)
740 n
= read(fd
, buf
, MAXCMD
);
742 fprintf(stderr
,"%s: read from mgmt %s",progname
,strerror(errno
));
749 rv
=handle_cmd(fd
,buf
);
751 write(fd
,prompt
,strlen(prompt
));
756 static int delmgmtconn(int i
,struct pollfd
*pfd
,int nfds
)
760 memmove(pfd
+i
,pfd
+i
+1,sizeof (struct pollfd
) * (nfds
-i
-1));
768 fprintf(stderr
,"Usage: %s OPTIONS\n"
770 "\t--loss|-l loss_percentage\n"
771 "\t--delay|-d delay_ms\n"
772 "\t--dup|-D dup_percentage\n"
773 "\t--band|-b bandwidth(bytes/s)\n"
774 "\t--speed|-s interface_speed(bytes/s)\n"
775 "\t--capacity|-c delay_channel_capacity\n"
776 "\t--noise|-n noise_bits/megabye\n"
777 "\t--mtu|-m mtu_size\n"
779 "\t--mgmt|-M management_socket\n"
780 "\t--mgmtmode management_permission(octal)\n"
785 int main(int argc
,char *argv
[])
791 static struct option long_options
[] = {
794 {"delay",1 , 0, 'd'},
797 {"speed",1 , 0, 's'},
798 {"capacity",1 , 0, 'c'},
799 {"noise",1 , 0, 'n'},
801 {"nofifo",0 , 0, 'N'},
803 {"mgmtmode", 1, 0, MGMTMODEARG
}
805 progname
=basename(argv
[0]);
810 ndirs
=check_open_fifos(pfd
,outfd
);
816 c
= GETOPT_LONG (argc
, argv
, "hnl:d:M:D:m:b:s:c:",
817 long_options
, &option_index
);
825 readdualvalue(optarg
,delay
,delayplus
);
828 readdualvalue(optarg
,loss
,lossplus
);
831 readdualvalue(optarg
,ddup
,ddupplus
);
834 readdualvalue(optarg
,band
,bandplus
);
837 readdualvalue(optarg
,mtu
,mtuplus
);
840 readdualvalue(optarg
,noise
,noiseplus
);
843 readdualvalue(optarg
,speed
,speedplus
);
846 readdualvalue(optarg
,capacity
,capacityplus
);
855 sscanf(optarg
,"%o",&mgmtmode
);
866 fprintf(stderr
,"%s: bidirectional filter starting...\n",progname
);
868 fprintf(stderr
,"%s: monodirectional filter starting...\n",progname
);
873 int mgmtfd
=openmgmt(mgmt
);
875 pfd
[mgmtindex
].fd
=mgmtfd
;
876 pfd
[mgmtindex
].events
=POLLIN
| POLLHUP
;
877 pfd
[mgmtindex
].revents
=0;
884 pfd
[0].events
|= POLLIN
;
888 gettimeofday(&tv
,NULL
);
889 if (timercmp(&tv
, &nextspeed
[LR
], <)) {
890 timersub(&nextspeed
[LR
],&tv
,&tv
);
891 speeddelay
=tv
.tv_sec
*1000 + tv
.tv_usec
/1000;
892 if (speeddelay
> 0) {
893 pfd
[0].events
&= ~POLLIN
;
894 if (speeddelay
< delay
|| delay
< 0) delay
=speeddelay
;
899 pfd
[1].events
|= POLLIN
;
903 if (timercmp(&tv
, &nextspeed
[RL
], <)) {
904 gettimeofday(&tv
,NULL
);
905 timersub(&nextspeed
[RL
],&tv
,&tv
);
906 speeddelay
=tv
.tv_sec
*1000 + tv
.tv_usec
/1000;
907 if (speeddelay
> 0) {
908 pfd
[1].events
&= ~POLLIN
;
909 if (speeddelay
< delay
|| delay
< 0) delay
=speeddelay
;
914 n
=poll(pfd
,npfd
,delay
);
915 if (pfd
[0].revents
& POLLHUP
|| (ndirs
>1 && pfd
[1].revents
& POLLHUP
))
917 if (pfd
[0].revents
& POLLIN
) {
920 if (ndirs
>1 && pfd
[1].revents
& POLLIN
) {
923 if (mgmtindex
>= 0) {
924 if (pfd
[mgmtindex
].revents
!= 0)
925 npfd
=newmgmtconn(pfd
[mgmtindex
].fd
,pfd
,npfd
);
926 if (npfd
> mgmtindex
+1) {
928 for (i
=mgmtindex
+1;i
<npfd
;i
++) {
929 if (pfd
[i
].revents
& POLLHUP
||
930 (pfd
[i
].revents
& POLLIN
&& mgmtcommand(pfd
[i
].fd
) < 0))
931 npfd
=delmgmtconn(i
,pfd
,npfd
);