xref: /freebsd/usr.sbin/ppp/physical.c (revision 2ad872c5794e4c26fdf6ed219ad3f09ca0d5304a)
1 /*
2  * Written by Eivind Eklund <eivind@yes.no>
3  *    for Yes Interactive
4  *
5  * Copyright (C) 1998, Yes Interactive.  All rights reserved.
6  *
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.
18  *
19  *  $Id: physical.c,v 1.6 1998/08/25 17:48:43 brian Exp $
20  *
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <unistd.h>
28 #include <utmp.h>
29 #include <sys/tty.h>
30 
31 #include "defs.h"
32 #include "mbuf.h"
33 #include "timer.h"
34 #include "lqr.h"
35 #include "hdlc.h"
36 #include "throughput.h"
37 #include "fsm.h"
38 #include "lcp.h"
39 #include "async.h"
40 #include "ccp.h"
41 #include "link.h"
42 #include "descriptor.h"
43 #include "physical.h"
44 #include "log.h"
45 #include "id.h"
46 
47 /* External calls - should possibly be moved inline */
48 extern int IntToSpeed(int);
49 
50 
51 int
52 physical_GetFD(struct physical *phys) {
53    return phys->fd;
54 }
55 
56 int
57 physical_IsSync(struct physical *phys) {
58    return phys->cfg.speed == 0;
59 }
60 
61 const char *physical_GetDevice(struct physical *phys)
62 {
63    return phys->name.full;
64 }
65 
66 void
67 physical_SetDeviceList(struct physical *p, int argc, const char *const *argv)
68 {
69   int f, pos;
70 
71   p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
72   for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) {
73     if (pos)
74       p->cfg.devlist[pos++] = ' ';
75     strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1);
76     pos += strlen(p->cfg.devlist + pos);
77   }
78 }
79 
80 
81 int
82 physical_SetSpeed(struct physical *phys, int speed) {
83    if (IntToSpeed(speed) != B0) {
84       phys->cfg.speed = speed;
85       return 1;
86    } else {
87       return 0;
88    }
89 }
90 
91 void
92 physical_SetSync(struct physical *phys) {
93    phys->cfg.speed = 0;
94 }
95 
96 
97 int
98 physical_SetRtsCts(struct physical *phys, int enable) {
99    phys->cfg.rts_cts = enable ? 1 : 0;
100    return 1;
101 }
102 
103 /* Encapsulation for a read on the FD.  Avoids some exposure, and
104    concentrates control. */
105 ssize_t
106 physical_Read(struct physical *phys, void *buf, size_t nbytes) {
107    return read(phys->fd, buf, nbytes);
108 }
109 
110 ssize_t
111 physical_Write(struct physical *phys, const void *buf, size_t nbytes) {
112    return write(phys->fd, buf, nbytes);
113 }
114 
115 int
116 physical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
117                    int *n, int force)
118 {
119   struct physical *p = descriptor2physical(d);
120   int sets;
121 
122   sets = 0;
123   if (p->fd >= 0) {
124     if (r) {
125       FD_SET(p->fd, r);
126       log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd);
127       sets++;
128     }
129     if (e) {
130       FD_SET(p->fd, e);
131       log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd);
132       sets++;
133     }
134     if (w && (force || link_QueueLen(&p->link) || p->out)) {
135       FD_SET(p->fd, w);
136       log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd);
137       sets++;
138     }
139     if (sets && *n < p->fd + 1)
140       *n = p->fd + 1;
141   }
142 
143   return sets;
144 }
145 
146 int
147 physical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e)
148 {
149   int sets;
150 
151   sets = 0;
152   if (p->fd >= 0) {
153     if (r && FD_ISSET(p->fd, r)) {
154       FD_CLR(p->fd, r);
155       log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd);
156       sets++;
157     }
158     if (e && FD_ISSET(p->fd, e)) {
159       FD_CLR(p->fd, e);
160       log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd);
161       sets++;
162     }
163     if (w && FD_ISSET(p->fd, w)) {
164       FD_CLR(p->fd, w);
165       log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd);
166       sets++;
167     }
168   }
169 
170   return sets;
171 }
172 
173 int
174 physical_IsSet(struct descriptor *d, const fd_set *fdset)
175 {
176   struct physical *p = descriptor2physical(d);
177   return p->fd >= 0 && FD_ISSET(p->fd, fdset);
178 }
179 
180 void
181 physical_Login(struct physical *phys, const char *name)
182 {
183   if (phys->type == PHYS_DIRECT && phys->isatty) {
184     if (phys->Utmp)
185       log_Printf(LogERROR, "Oops, already logged in on %s\n", phys->name.base);
186     else {
187       struct utmp ut;
188       const char *connstr;
189 
190       memset(&ut, 0, sizeof ut);
191       time(&ut.ut_time);
192       strncpy(ut.ut_name, name, sizeof ut.ut_name);
193       strncpy(ut.ut_line, phys->name.base, sizeof ut.ut_line);
194       if ((connstr = getenv("CONNECT")))
195         /* mgetty sets this to the connection speed */
196         strncpy(ut.ut_host, connstr, sizeof ut.ut_host);
197       ID0login(&ut);
198       phys->Utmp = 1;
199     }
200   }
201 }
202 
203 void
204 physical_Logout(struct physical *phys)
205 {
206   if (phys->Utmp) {
207     ID0logout(phys->name.base);
208     phys->Utmp = 0;
209   }
210 }
211 
212 int
213 physical_SetMode(struct physical *p, int mode)
214 {
215   if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) ||
216        mode & (PHYS_DIRECT|PHYS_DEDICATED)) &&
217       (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) {
218     log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name,
219                mode2Nam(p->type), mode2Nam(mode));
220     return 0;
221   }
222   p->type = mode;
223   return 1;
224 }
225 
226 void
227 physical_DeleteQueue(struct physical *p)
228 {
229   if (p->out) {
230     mbuf_Free(p->out);
231     p->out = NULL;
232   }
233   link_DeleteQueue(&p->link);
234 }
235