2 * Written by Eivind Eklund <eivind@yes.no>
5 * Copyright (C) 1998, Yes Interactive. All rights reserved.
7 * Redistribution and use in any form is permitted. Redistribution in
8 * source form should include the above copyright and this set of
9 * conditions, because large sections american law seems to have been
10 * created by a bunch of jerks on drugs that are now illegal, forcing
11 * me to include this copyright-stuff instead of placing this in the
12 * public domain. The name of of 'Yes Interactive' or 'Eivind Eklund'
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 #include <sys/param.h>
24 #include <netinet/in.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/ip.h>
27 #include <sys/socket.h>
46 #if defined(__OpenBSD__) || defined(__NetBSD__)
47 #include <sys/ioctl.h>
70 #include "throughput.h"
74 #include "slcompress.h"
78 #include "descriptor.h"
102 #include "netgraph.h"
109 #define PPPOTCPLINE "ppp"
111 static int physical_DescriptorWrite(struct fdescriptor
*, struct bundle
*,
115 physical_DeviceSize(void)
117 return sizeof(struct device
);
121 struct device
*(*create
)(struct physical
*);
122 struct device
*(*iov2device
)(int, struct physical
*, struct iovec
*,
123 int *, int, int *, int *);
124 unsigned (*DeviceSize
)(void);
126 { tty_Create
, tty_iov2device
, tty_DeviceSize
},
129 * This must come before ``udp'' so that the probe routine is
130 * able to identify it as a more specific type of SOCK_DGRAM.
132 { ether_Create
, ether_iov2device
, ether_DeviceSize
},
133 #ifdef EXPERIMENTAL_NETGRAPH
134 { ng_Create
, ng_iov2device
, ng_DeviceSize
},
138 /* Ditto for ATM devices */
139 { atm_Create
, atm_iov2device
, atm_DeviceSize
},
141 { tcp_Create
, tcp_iov2device
, tcp_DeviceSize
},
142 { udp_Create
, udp_iov2device
, udp_DeviceSize
},
143 { exec_Create
, exec_iov2device
, exec_DeviceSize
}
146 #define NDEVICES (sizeof devices / sizeof devices[0])
149 physical_UpdateSet(struct fdescriptor
*d
, fd_set
*r
, fd_set
*w
, fd_set
*e
,
152 return physical_doUpdateSet(d
, r
, w
, e
, n
, 0);
156 physical_SetDescriptor(struct physical
*p
)
158 p
->desc
.type
= PHYSICAL_DESCRIPTOR
;
159 p
->desc
.UpdateSet
= physical_UpdateSet
;
160 p
->desc
.IsSet
= physical_IsSet
;
161 p
->desc
.Read
= physical_DescriptorRead
;
162 p
->desc
.Write
= physical_DescriptorWrite
;
166 physical_Create(struct datalink
*dl
, int type
)
170 p
= (struct physical
*)malloc(sizeof(struct physical
));
174 p
->link
.type
= PHYSICAL_LINK
;
175 p
->link
.name
= dl
->name
;
176 p
->link
.len
= sizeof *p
;
178 /* The sample period is fixed - see physical2iov() & iov2physical() */
179 throughput_init(&p
->link
.stats
.total
, SAMPLE_PERIOD
);
180 p
->link
.stats
.parent
= dl
->bundle
->ncp
.mp
.active
?
181 &dl
->bundle
->ncp
.mp
.link
.stats
.total
: NULL
;
182 p
->link
.stats
.gather
= 1;
184 memset(p
->link
.Queue
, '\0', sizeof p
->link
.Queue
);
185 memset(p
->link
.proto_in
, '\0', sizeof p
->link
.proto_in
);
186 memset(p
->link
.proto_out
, '\0', sizeof p
->link
.proto_out
);
187 link_EmptyStack(&p
->link
);
190 physical_SetDescriptor(p
);
193 hdlc_Init(&p
->hdlc
, &p
->link
.lcp
);
194 async_Init(&p
->async
);
198 p
->connect_count
= 0;
201 *p
->name
.full
= '\0';
202 p
->name
.base
= p
->name
.full
;
205 p
->session_owner
= (pid_t
)-1;
207 p
->cfg
.rts_cts
= MODEM_CTSRTS
;
208 p
->cfg
.speed
= MODEM_SPEED
;
210 memcpy(p
->cfg
.devlist
, MODEM_LIST
, sizeof MODEM_LIST
);
211 p
->cfg
.ndev
= NMODEMS
;
212 p
->cfg
.cd
.necessity
= CD_DEFAULT
;
213 p
->cfg
.cd
.delay
= 0; /* reconfigured or device specific default */
215 lcp_Init(&p
->link
.lcp
, dl
->bundle
, &p
->link
, &dl
->fsmp
);
216 ccp_Init(&p
->link
.ccp
, dl
->bundle
, &p
->link
, &dl
->fsmp
);
221 static const struct parity
{
226 { "even", "P_EVEN", CS7
| PARENB
},
227 { "odd", "P_ODD", CS7
| PARENB
| PARODD
},
228 { "none", "P_ZERO", CS8
},
233 GetParityValue(const char *str
)
235 const struct parity
*pp
;
237 for (pp
= validparity
; pp
->name
; pp
++) {
238 if (strcasecmp(pp
->name
, str
) == 0 ||
239 strcasecmp(pp
->name1
, str
) == 0) {
247 physical_SetParity(struct physical
*p
, const char *str
)
249 struct termios rstio
;
252 val
= GetParityValue(str
);
256 tcgetattr(p
->fd
, &rstio
);
257 rstio
.c_cflag
&= ~(CSIZE
| PARODD
| PARENB
);
258 rstio
.c_cflag
|= val
;
259 tcsetattr(p
->fd
, TCSADRAIN
, &rstio
);
263 log_Printf(LogWARN
, "%s: %s: Invalid parity\n", p
->link
.name
, str
);
268 physical_GetSpeed(struct physical
*p
)
270 if (p
->handler
&& p
->handler
->speed
)
271 return (*p
->handler
->speed
)(p
);
277 physical_SetSpeed(struct physical
*p
, unsigned speed
)
279 if (UnsignedToSpeed(speed
) != B0
) {
280 p
->cfg
.speed
= speed
;
288 physical_Raw(struct physical
*p
)
290 if (p
->handler
&& p
->handler
->raw
)
291 return (*p
->handler
->raw
)(p
);
297 physical_Offline(struct physical
*p
)
299 if (p
->handler
&& p
->handler
->offline
)
300 (*p
->handler
->offline
)(p
);
301 log_Printf(LogPHASE
, "%s: Disconnected!\n", p
->link
.name
);
305 physical_Lock(struct physical
*p
)
309 if (*p
->name
.full
== '/' && p
->type
!= PHYS_DIRECT
&&
310 (res
= ID0uu_lock(p
->name
.base
)) != UU_LOCK_OK
) {
311 if (res
== UU_LOCK_INUSE
)
312 log_Printf(LogPHASE
, "%s: %s is in use\n", p
->link
.name
, p
->name
.full
);
314 log_Printf(LogPHASE
, "%s: %s is in use: uu_lock: %s\n",
315 p
->link
.name
, p
->name
.full
, uu_lockerr(res
));
323 physical_Unlock(struct physical
*p
)
325 if (*p
->name
.full
== '/' && p
->type
!= PHYS_DIRECT
&&
326 ID0uu_unlock(p
->name
.base
) == -1)
327 log_Printf(LogALERT
, "%s: Can't uu_unlock %s\n", p
->link
.name
,
332 physical_Close(struct physical
*p
)
340 log_Printf(LogDEBUG
, "%s: Close\n", p
->link
.name
);
342 if (p
->handler
&& p
->handler
->cooked
)
343 (*p
->handler
->cooked
)(p
);
345 physical_StopDeviceTimer(p
);
347 if (p
->handler
&& (p
->handler
->type
== TCP_DEVICE
||
348 p
->handler
->type
== UDP_DEVICE
))
349 /* Careful - we logged in on line ``ppp'' with IP as our host */
350 ID0logout(PPPOTCPLINE
, 1);
352 ID0logout(p
->name
.base
, 0);
355 newsid
= tcgetpgrp(p
->fd
) == getpgrp();
358 log_SetTtyCommandMode(p
->dl
);
360 throughput_stop(&p
->link
.stats
.total
);
361 throughput_log(&p
->link
.stats
.total
, LogPHASE
, p
->link
.name
);
363 if (p
->session_owner
!= (pid_t
)-1) {
364 log_Printf(LogPHASE
, "%s: HUPing %ld\n", p
->link
.name
,
365 (long)p
->session_owner
);
366 ID0kill(p
->session_owner
, SIGHUP
);
367 p
->session_owner
= (pid_t
)-1;
371 bundle_setsid(p
->dl
->bundle
, 0);
373 if (*p
->name
.full
== '/') {
374 snprintf(fn
, sizeof fn
, "%s%s.if", _PATH_VARRUN
, p
->name
.base
);
375 #ifndef RELEASE_CRUNCH
376 if (ID0unlink(fn
) == -1)
377 log_Printf(LogALERT
, "%s: Can't remove %s: %s\n",
378 p
->link
.name
, fn
, strerror(errno
));
384 if (p
->handler
&& p
->handler
->destroy
)
385 (*p
->handler
->destroy
)(p
);
387 p
->name
.base
= p
->name
.full
;
388 *p
->name
.full
= '\0';
392 physical_Destroy(struct physical
*p
)
395 throughput_destroy(&p
->link
.stats
.total
);
400 physical_DescriptorWrite(struct fdescriptor
*d
, struct bundle
*bundle __unused
,
401 const fd_set
*fdset __unused
)
403 struct physical
*p
= descriptor2physical(d
);
407 p
->out
= link_Dequeue(&p
->link
);
410 nw
= physical_Write(p
, MBUF_CTOP(p
->out
), p
->out
->m_len
);
411 log_Printf(LogDEBUG
, "%s: DescriptorWrite: wrote %d(%lu) to %d\n",
412 p
->link
.name
, nw
, (unsigned long)p
->out
->m_len
, p
->fd
);
415 p
->out
->m_offset
+= nw
;
416 if (p
->out
->m_len
== 0)
417 p
->out
= m_free(p
->out
);
422 else if (errno
!= ENOBUFS
) {
423 log_Printf(LogPHASE
, "%s: write (fd %d, len %zd): %s\n", p
->link
.name
,
424 p
->fd
, p
->out
->m_len
, strerror(errno
));
425 datalink_Down(p
->dl
, CLOSE_NORMAL
);
428 /* else we shouldn't really have been called ! select() is broken ! */
435 physical_ShowStatus(struct cmdargs
const *arg
)
437 struct physical
*p
= arg
->cx
->physical
;
442 prompt_Printf(arg
->prompt
, "Name: %s\n", p
->link
.name
);
443 prompt_Printf(arg
->prompt
, " State: ");
445 prompt_Printf(arg
->prompt
, "closed\n");
447 slot
= physical_Slot(p
);
448 if (p
->handler
&& p
->handler
->openinfo
) {
450 prompt_Printf(arg
->prompt
, "open (%s)\n", (*p
->handler
->openinfo
)(p
));
452 prompt_Printf(arg
->prompt
, "open (%s, port %d)\n",
453 (*p
->handler
->openinfo
)(p
), slot
);
454 } else if (slot
== -1)
455 prompt_Printf(arg
->prompt
, "open\n");
457 prompt_Printf(arg
->prompt
, "open (port %d)\n", slot
);
460 prompt_Printf(arg
->prompt
, " Device: %s",
461 *p
->name
.full
? p
->name
.full
:
462 p
->type
== PHYS_DIRECT
? "unknown" : "N/A");
463 if (p
->session_owner
!= (pid_t
)-1)
464 prompt_Printf(arg
->prompt
, " (session owner: %ld)", (long)p
->session_owner
);
466 prompt_Printf(arg
->prompt
, "\n Link Type: %s\n", mode2Nam(p
->type
));
467 prompt_Printf(arg
->prompt
, " Connect Count: %d\n", p
->connect_count
);
469 if (p
->fd
>= 0 && ioctl(p
->fd
, TIOCOUTQ
, &n
) >= 0)
470 prompt_Printf(arg
->prompt
, " Physical outq: %d\n", n
);
473 prompt_Printf(arg
->prompt
, " Queued Packets: %lu\n",
474 (u_long
)link_QueueLen(&p
->link
));
475 prompt_Printf(arg
->prompt
, " Phone Number: %s\n", arg
->cx
->phone
.chosen
);
477 prompt_Printf(arg
->prompt
, "\nDefaults:\n");
479 prompt_Printf(arg
->prompt
, " Device List: ");
480 dev
= p
->cfg
.devlist
;
481 for (n
= 0; n
< p
->cfg
.ndev
; n
++) {
483 prompt_Printf(arg
->prompt
, ", ");
484 prompt_Printf(arg
->prompt
, "\"%s\"", dev
);
485 dev
+= strlen(dev
) + 1;
488 prompt_Printf(arg
->prompt
, "\n Characteristics: ");
489 if (physical_IsSync(arg
->cx
->physical
))
490 prompt_Printf(arg
->prompt
, "sync");
492 prompt_Printf(arg
->prompt
, "%dbps", p
->cfg
.speed
);
494 switch (p
->cfg
.parity
& CSIZE
) {
496 prompt_Printf(arg
->prompt
, ", cs7");
499 prompt_Printf(arg
->prompt
, ", cs8");
502 if (p
->cfg
.parity
& PARENB
) {
503 if (p
->cfg
.parity
& PARODD
)
504 prompt_Printf(arg
->prompt
, ", odd parity");
506 prompt_Printf(arg
->prompt
, ", even parity");
508 prompt_Printf(arg
->prompt
, ", no parity");
510 prompt_Printf(arg
->prompt
, ", CTS/RTS %s\n", (p
->cfg
.rts_cts
? "on" : "off"));
512 prompt_Printf(arg
->prompt
, " CD check delay: ");
513 cd
= p
->handler
? &p
->handler
->cd
: &p
->cfg
.cd
;
514 if (cd
->necessity
== CD_NOTREQUIRED
)
515 prompt_Printf(arg
->prompt
, "no cd");
516 else if (p
->cfg
.cd
.necessity
== CD_DEFAULT
) {
517 prompt_Printf(arg
->prompt
, "device specific");
519 prompt_Printf(arg
->prompt
, "%d second%s", p
->cfg
.cd
.delay
,
520 p
->cfg
.cd
.delay
== 1 ? "" : "s");
521 if (p
->cfg
.cd
.necessity
== CD_REQUIRED
)
522 prompt_Printf(arg
->prompt
, " (required!)");
524 prompt_Printf(arg
->prompt
, "\n\n");
526 throughput_disp(&p
->link
.stats
.total
, arg
->prompt
);
532 physical_DescriptorRead(struct fdescriptor
*d
, struct bundle
*bundle
,
533 const fd_set
*fdset __unused
)
535 struct physical
*p
= descriptor2physical(d
);
539 rbuff
= p
->input
.buf
+ p
->input
.sz
;
541 /* something to read */
542 n
= physical_Read(p
, rbuff
, sizeof p
->input
.buf
- p
->input
.sz
);
543 log_Printf(LogDEBUG
, "%s: DescriptorRead: read %d/%d from %d\n",
544 p
->link
.name
, n
, (int)(sizeof p
->input
.buf
- p
->input
.sz
), p
->fd
);
547 log_Printf(LogPHASE
, "%s: read (%d): %s\n", p
->link
.name
, p
->fd
,
550 log_Printf(LogPHASE
, "%s: read (%d): Got zero bytes\n",
551 p
->link
.name
, p
->fd
);
552 datalink_Down(p
->dl
, CLOSE_NORMAL
);
556 rbuff
-= p
->input
.sz
;
559 if (p
->link
.lcp
.fsm
.state
<= ST_CLOSED
) {
560 if (p
->type
!= PHYS_DEDICATED
) {
561 found
= hdlc_Detect((u_char
const **)&rbuff
, n
, physical_IsSync(p
));
562 if (rbuff
!= p
->input
.buf
)
563 log_WritePrompts(p
->dl
, "%.*s", (int)(rbuff
- p
->input
.buf
),
565 p
->input
.sz
= n
- (rbuff
- p
->input
.buf
);
568 /* LCP packet is detected. Turn ourselves into packet mode */
569 log_Printf(LogPHASE
, "%s: PPP packet detected, coming up\n",
571 log_SetTtyCommandMode(p
->dl
);
572 datalink_Up(p
->dl
, 0, 1);
573 link_PullPacket(&p
->link
, rbuff
, p
->input
.sz
, bundle
);
576 bcopy(rbuff
, p
->input
.buf
, p
->input
.sz
);
578 /* In -dedicated mode, we just discard input until LCP is started */
581 link_PullPacket(&p
->link
, rbuff
, n
, bundle
);
585 iov2physical(struct datalink
*dl
, struct iovec
*iov
, int *niov
, int maxiov
,
586 int fd
, int *auxfd
, int *nauxfd
)
592 p
= (struct physical
*)iov
[(*niov
)++].iov_base
;
593 p
->link
.name
= dl
->name
;
594 memset(p
->link
.Queue
, '\0', sizeof p
->link
.Queue
);
596 p
->desc
.UpdateSet
= physical_UpdateSet
;
597 p
->desc
.IsSet
= physical_IsSet
;
598 p
->desc
.Read
= physical_DescriptorRead
;
599 p
->desc
.Write
= physical_DescriptorWrite
;
600 p
->type
= PHYS_DIRECT
;
602 len
= strlen(_PATH_DEV
);
604 p
->connect_count
= 1;
606 physical_SetDevice(p
, p
->name
.full
);
608 p
->link
.lcp
.fsm
.bundle
= dl
->bundle
;
609 p
->link
.lcp
.fsm
.link
= &p
->link
;
610 memset(&p
->link
.lcp
.fsm
.FsmTimer
, '\0', sizeof p
->link
.lcp
.fsm
.FsmTimer
);
611 memset(&p
->link
.lcp
.fsm
.OpenTimer
, '\0', sizeof p
->link
.lcp
.fsm
.OpenTimer
);
612 memset(&p
->link
.lcp
.fsm
.StoppedTimer
, '\0',
613 sizeof p
->link
.lcp
.fsm
.StoppedTimer
);
614 p
->link
.lcp
.fsm
.parent
= &dl
->fsmp
;
615 lcp_SetupCallbacks(&p
->link
.lcp
);
617 p
->link
.ccp
.fsm
.bundle
= dl
->bundle
;
618 p
->link
.ccp
.fsm
.link
= &p
->link
;
619 /* Our in.state & out.state are NULL (no link-level ccp yet) */
620 memset(&p
->link
.ccp
.fsm
.FsmTimer
, '\0', sizeof p
->link
.ccp
.fsm
.FsmTimer
);
621 memset(&p
->link
.ccp
.fsm
.OpenTimer
, '\0', sizeof p
->link
.ccp
.fsm
.OpenTimer
);
622 memset(&p
->link
.ccp
.fsm
.StoppedTimer
, '\0',
623 sizeof p
->link
.ccp
.fsm
.StoppedTimer
);
624 p
->link
.ccp
.fsm
.parent
= &dl
->fsmp
;
625 ccp_SetupCallbacks(&p
->link
.ccp
);
627 p
->hdlc
.lqm
.owner
= &p
->link
.lcp
;
628 p
->hdlc
.ReportTimer
.state
= TIMER_STOPPED
;
629 p
->hdlc
.lqm
.timer
.state
= TIMER_STOPPED
;
632 p
->link
.stats
.total
.in
.SampleOctets
= (long long *)iov
[(*niov
)++].iov_base
;
633 p
->link
.stats
.total
.out
.SampleOctets
= (long long *)iov
[(*niov
)++].iov_base
;
634 p
->link
.stats
.parent
= dl
->bundle
->ncp
.mp
.active
?
635 &dl
->bundle
->ncp
.mp
.link
.stats
.total
: NULL
;
636 p
->link
.stats
.gather
= 1;
638 type
= (long)p
->handler
;
640 for (h
= 0; h
< NDEVICES
&& p
->handler
== NULL
; h
++)
641 p
->handler
= (*devices
[h
].iov2device
)(type
, p
, iov
, niov
, maxiov
,
643 if (p
->handler
== NULL
) {
644 log_Printf(LogPHASE
, "%s: Unknown link type\n", p
->link
.name
);
645 free(iov
[(*niov
)++].iov_base
);
646 physical_SetupStack(p
, "unknown", PHYSICAL_NOFORCE
);
648 log_Printf(LogPHASE
, "%s: Device %s, link type is %s\n",
649 p
->link
.name
, p
->name
.full
, p
->handler
->name
);
651 if (p
->hdlc
.lqm
.method
&& p
->hdlc
.lqm
.timer
.load
)
652 lqr_reStart(&p
->link
.lcp
);
653 hdlc_StartTimer(&p
->hdlc
);
655 throughput_restart(&p
->link
.stats
.total
, "physical throughput",
656 Enabled(dl
->bundle
, OPT_THROUGHPUT
));
662 physical_MaxDeviceSize()
664 unsigned biggest
, sz
, n
;
666 biggest
= sizeof(struct device
);
667 for (n
= 0; n
< NDEVICES
; n
++)
668 if (devices
[n
].DeviceSize
) {
669 sz
= (*devices
[n
].DeviceSize
)();
678 physical2iov(struct physical
*p
, struct iovec
*iov
, int *niov
, int maxiov
,
679 int *auxfd
, int *nauxfd
)
686 hdlc_StopTimer(&p
->hdlc
);
688 timer_Stop(&p
->link
.lcp
.fsm
.FsmTimer
);
689 timer_Stop(&p
->link
.ccp
.fsm
.FsmTimer
);
690 timer_Stop(&p
->link
.lcp
.fsm
.OpenTimer
);
691 timer_Stop(&p
->link
.ccp
.fsm
.OpenTimer
);
692 timer_Stop(&p
->link
.lcp
.fsm
.StoppedTimer
);
693 timer_Stop(&p
->link
.ccp
.fsm
.StoppedTimer
);
696 p
->handler
= (struct device
*)(long)p
->handler
->type
;
699 if (Enabled(p
->dl
->bundle
, OPT_KEEPSESSION
) ||
700 tcgetpgrp(p
->fd
) == getpgrp())
701 p
->session_owner
= getpid(); /* So I'll eventually get HUP'd */
703 p
->session_owner
= (pid_t
)-1;
704 timer_Stop(&p
->link
.stats
.total
.Timer
);
707 if (*niov
+ 2 >= maxiov
) {
708 log_Printf(LogERROR
, "physical2iov: No room for physical + throughput"
715 iov
[*niov
].iov_base
= (void *)p
;
716 iov
[*niov
].iov_len
= sizeof *p
;
719 iov
[*niov
].iov_base
= p
? (void *)p
->link
.stats
.total
.in
.SampleOctets
: NULL
;
720 iov
[*niov
].iov_len
= SAMPLE_PERIOD
* sizeof(long long);
722 iov
[*niov
].iov_base
= p
? (void *)p
->link
.stats
.total
.out
.SampleOctets
: NULL
;
723 iov
[*niov
].iov_len
= SAMPLE_PERIOD
* sizeof(long long);
726 sz
= physical_MaxDeviceSize();
728 if (h
&& h
->device2iov
)
729 (*h
->device2iov
)(h
, iov
, niov
, maxiov
, auxfd
, nauxfd
);
731 if ((iov
[*niov
].iov_base
= malloc(sz
)) == NULL
) {
732 log_Printf(LogALERT
, "physical2iov: Out of memory (%d bytes)\n", sz
);
733 AbortProgram(EX_OSERR
);
736 memcpy(iov
[*niov
].iov_base
, h
, sizeof *h
);
737 iov
[*niov
].iov_len
= sz
;
741 iov
[*niov
].iov_base
= NULL
;
742 iov
[*niov
].iov_len
= sz
;
746 return p
? p
->fd
: 0;
750 physical_LockedDevice(struct physical
*p
)
752 if (p
->fd
>= 0 && *p
->name
.full
== '/' && p
->type
!= PHYS_DIRECT
)
759 physical_ChangedPid(struct physical
*p
, pid_t newpid
)
761 if (physical_LockedDevice(p
)) {
764 if ((res
= ID0uu_lock_txfr(p
->name
.base
, newpid
)) != UU_LOCK_OK
)
765 log_Printf(LogPHASE
, "uu_lock_txfr: %s\n", uu_lockerr(res
));
770 physical_IsSync(struct physical
*p
)
772 return p
->cfg
.speed
== 0;
776 physical_DeviceMTU(struct physical
*p
)
778 return p
->handler
? p
->handler
->mtu
: 0;
781 const char *physical_GetDevice(struct physical
*p
)
787 physical_SetDeviceList(struct physical
*p
, int argc
, const char *const *argv
)
792 p
->cfg
.devlist
[sizeof p
->cfg
.devlist
- 1] = '\0';
793 for (f
= 0, pos
= 0; f
< argc
&& pos
< sizeof p
->cfg
.devlist
- 1; f
++) {
795 p
->cfg
.devlist
[pos
++] = '\0';
796 strncpy(p
->cfg
.devlist
+ pos
, argv
[f
], sizeof p
->cfg
.devlist
- pos
- 1);
797 pos
+= strlen(p
->cfg
.devlist
+ pos
);
803 physical_SetSync(struct physical
*p
)
809 physical_SetRtsCts(struct physical
*p
, int enable
)
811 p
->cfg
.rts_cts
= enable
? 1 : 0;
816 physical_Read(struct physical
*p
, void *buf
, size_t nbytes
)
820 if (p
->handler
&& p
->handler
->read
)
821 ret
= (*p
->handler
->read
)(p
, buf
, nbytes
);
823 ret
= read(p
->fd
, buf
, nbytes
);
825 log_DumpBuff(LogPHYSICAL
, "read", buf
, ret
);
831 physical_Write(struct physical
*p
, const void *buf
, size_t nbytes
)
833 log_DumpBuff(LogPHYSICAL
, "write", buf
, nbytes
);
835 if (p
->handler
&& p
->handler
->write
)
836 return (*p
->handler
->write
)(p
, buf
, nbytes
);
838 return write(p
->fd
, buf
, nbytes
);
842 physical_doUpdateSet(struct fdescriptor
*d
, fd_set
*r
, fd_set
*w
, fd_set
*e
,
845 struct physical
*p
= descriptor2physical(d
);
852 log_Printf(LogTIMER
, "%s: fdset(r) %d\n", p
->link
.name
, p
->fd
);
857 log_Printf(LogTIMER
, "%s: fdset(e) %d\n", p
->link
.name
, p
->fd
);
860 if (w
&& (force
|| link_QueueLen(&p
->link
) || p
->out
)) {
862 log_Printf(LogTIMER
, "%s: fdset(w) %d\n", p
->link
.name
, p
->fd
);
865 if (sets
&& *n
< p
->fd
+ 1)
873 physical_RemoveFromSet(struct physical
*p
, fd_set
*r
, fd_set
*w
, fd_set
*e
)
875 if (p
->handler
&& p
->handler
->removefromset
)
876 return (*p
->handler
->removefromset
)(p
, r
, w
, e
);
882 if (r
&& FD_ISSET(p
->fd
, r
)) {
884 log_Printf(LogTIMER
, "%s: fdunset(r) %d\n", p
->link
.name
, p
->fd
);
887 if (e
&& FD_ISSET(p
->fd
, e
)) {
889 log_Printf(LogTIMER
, "%s: fdunset(e) %d\n", p
->link
.name
, p
->fd
);
892 if (w
&& FD_ISSET(p
->fd
, w
)) {
894 log_Printf(LogTIMER
, "%s: fdunset(w) %d\n", p
->link
.name
, p
->fd
);
904 physical_IsSet(struct fdescriptor
*d
, const fd_set
*fdset
)
906 struct physical
*p
= descriptor2physical(d
);
907 return p
->fd
>= 0 && FD_ISSET(p
->fd
, fdset
);
911 physical_Login(struct physical
*p
, const char *name
)
913 if (p
->type
== PHYS_DIRECT
&& *p
->name
.base
&& !p
->Utmp
) {
918 memset(&ut
, 0, sizeof ut
);
919 ut
.ut_time
= time(NULL
);
920 strncpy(ut
.ut_name
, name
, sizeof ut
.ut_name
);
921 if (p
->handler
&& (p
->handler
->type
== TCP_DEVICE
||
922 p
->handler
->type
== UDP_DEVICE
)) {
923 strncpy(ut
.ut_line
, PPPOTCPLINE
, sizeof ut
.ut_line
);
924 strncpy(ut
.ut_host
, p
->name
.base
, sizeof ut
.ut_host
);
925 colon
= memchr(ut
.ut_host
, ':', sizeof ut
.ut_host
);
929 strncpy(ut
.ut_line
, p
->name
.base
, sizeof ut
.ut_line
);
930 if ((connstr
= getenv("CONNECT")))
931 /* mgetty sets this to the connection speed */
932 strncpy(ut
.ut_host
, connstr
, sizeof ut
.ut_host
);
934 p
->Utmp
= ut
.ut_time
;
939 physical_SetMode(struct physical
*p
, int mode
)
941 if ((p
->type
& (PHYS_DIRECT
|PHYS_DEDICATED
) ||
942 mode
& (PHYS_DIRECT
|PHYS_DEDICATED
)) &&
943 (!(p
->type
& PHYS_DIRECT
) || !(mode
& PHYS_BACKGROUND
))) {
944 /* Note: The -direct -> -background is for callback ! */
945 log_Printf(LogWARN
, "%s: Cannot change mode %s to %s\n", p
->link
.name
,
946 mode2Nam(p
->type
), mode2Nam(mode
));
954 physical_DeleteQueue(struct physical
*p
)
960 link_DeleteQueue(&p
->link
);
964 physical_SetDevice(struct physical
*p
, const char *name
)
966 int len
= strlen(_PATH_DEV
);
968 if (name
!= p
->name
.full
) {
969 strncpy(p
->name
.full
, name
, sizeof p
->name
.full
- 1);
970 p
->name
.full
[sizeof p
->name
.full
- 1] = '\0';
972 p
->name
.base
= *p
->name
.full
== '!' ? p
->name
.full
+ 1 :
973 strncmp(p
->name
.full
, _PATH_DEV
, len
) ?
974 p
->name
.full
: p
->name
.full
+ len
;
978 physical_Found(struct physical
*p
)
983 if (*p
->name
.full
== '/') {
984 snprintf(fn
, sizeof fn
, "%s%s.if", _PATH_VARRUN
, p
->name
.base
);
985 lockfile
= ID0fopen(fn
, "w");
986 if (lockfile
!= NULL
) {
987 fprintf(lockfile
, "%s%d\n", TUN_NAME
, p
->dl
->bundle
->unit
);
990 #ifndef RELEASE_CRUNCH
992 log_Printf(LogALERT
, "%s: Can't create %s: %s\n",
993 p
->link
.name
, fn
, strerror(errno
));
997 throughput_start(&p
->link
.stats
.total
, "physical throughput",
998 Enabled(p
->dl
->bundle
, OPT_THROUGHPUT
));
1002 log_Printf(LogPHASE
, "%s: Connected!\n", p
->link
.name
);
1006 physical_Open(struct physical
*p
)
1009 int devno
, wasfd
, err
;
1013 log_Printf(LogDEBUG
, "%s: Open: Modem is already open!\n", p
->link
.name
);
1014 /* We're going back into "term" mode */
1015 else if (p
->type
== PHYS_DIRECT
) {
1016 physical_SetDevice(p
, "");
1017 p
->fd
= STDIN_FILENO
;
1018 for (h
= 0; h
< NDEVICES
&& p
->handler
== NULL
&& p
->fd
>= 0; h
++)
1019 p
->handler
= (*devices
[h
].create
)(p
);
1021 if (p
->handler
== NULL
) {
1022 physical_SetupStack(p
, "unknown", PHYSICAL_NOFORCE
);
1023 log_Printf(LogDEBUG
, "%s: stdin is unidentified\n", p
->link
.name
);
1028 dev
= p
->cfg
.devlist
;
1030 while (devno
< p
->cfg
.ndev
&& p
->fd
< 0) {
1031 physical_SetDevice(p
, dev
);
1032 if (physical_Lock(p
)) {
1035 if (*p
->name
.full
== '/') {
1036 p
->fd
= ID0open(p
->name
.full
, O_RDWR
| O_NONBLOCK
);
1042 for (h
= 0; h
< NDEVICES
&& p
->handler
== NULL
; h
++)
1043 if ((p
->handler
= (*devices
[h
].create
)(p
)) == NULL
&& wasfd
!= p
->fd
)
1047 if (h
== NDEVICES
) {
1049 log_Printf(LogWARN
, "%s: %s: %s\n", p
->link
.name
, p
->name
.full
,
1052 log_Printf(LogWARN
, "%s: Device (%s) must begin with a '/',"
1053 " a '!' or contain at least one ':'\n", p
->link
.name
,
1060 dev
+= strlen(dev
) + 1;
1069 physical_SetupStack(struct physical
*p
, const char *who
, int how
)
1071 link_EmptyStack(&p
->link
);
1072 if (how
== PHYSICAL_FORCE_SYNC
|| how
== PHYSICAL_FORCE_SYNCNOACF
||
1073 (how
== PHYSICAL_NOFORCE
&& physical_IsSync(p
)))
1074 link_Stack(&p
->link
, &synclayer
);
1076 link_Stack(&p
->link
, &asynclayer
);
1077 link_Stack(&p
->link
, &hdlclayer
);
1079 if (how
!= PHYSICAL_FORCE_SYNCNOACF
)
1080 link_Stack(&p
->link
, &acflayer
);
1081 link_Stack(&p
->link
, &protolayer
);
1082 link_Stack(&p
->link
, &lqrlayer
);
1083 link_Stack(&p
->link
, &ccplayer
);
1084 link_Stack(&p
->link
, &vjlayer
);
1085 link_Stack(&p
->link
, &tcpmsslayer
);
1087 link_Stack(&p
->link
, &natlayer
);
1089 if (how
== PHYSICAL_FORCE_ASYNC
&& physical_IsSync(p
)) {
1090 log_Printf(LogWARN
, "Sync device setting ignored for ``%s'' device\n", who
);
1091 p
->cfg
.speed
= MODEM_SPEED
;
1092 } else if (how
== PHYSICAL_FORCE_SYNC
&& !physical_IsSync(p
)) {
1093 log_Printf(LogWARN
, "Async device setting ignored for ``%s'' device\n",
1095 physical_SetSync(p
);
1100 physical_StopDeviceTimer(struct physical
*p
)
1102 if (p
->handler
&& p
->handler
->stoptimer
)
1103 (*p
->handler
->stoptimer
)(p
);
1107 physical_AwaitCarrier(struct physical
*p
)
1109 if (p
->handler
&& p
->handler
->awaitcarrier
)
1110 return (*p
->handler
->awaitcarrier
)(p
);
1117 physical_SetAsyncParams(struct physical
*p
, u_int32_t mymap
, u_int32_t hismap
)
1119 if (p
->handler
&& p
->handler
->setasyncparams
)
1120 return (*p
->handler
->setasyncparams
)(p
, mymap
, hismap
);
1122 async_SetLinkParams(&p
->async
, mymap
, hismap
);
1126 physical_Slot(struct physical
*p
)
1128 if (p
->handler
&& p
->handler
->slot
)
1129 return (*p
->handler
->slot
)(p
);
1135 physical_SetPPPoEnonstandard(struct physical
*p
, int enable
)
1137 p
->cfg
.nonstandard_pppoe
= enable
? 1 : 0;
1138 p
->cfg
.pppoe_configured
= 1;