xref: /freebsd/usr.sbin/ppp/physical.c (revision 380a989b3223d455375b4fae70fd0b9bdd43bafb)
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.5 1998/08/07 18:42:50 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_IsATTY(struct physical *phys) {
58    return isatty(phys->fd);
59 }
60 
61 int
62 physical_IsSync(struct physical *phys) {
63    return phys->cfg.speed == 0;
64 }
65 
66 const char *physical_GetDevice(struct physical *phys)
67 {
68    return phys->name.full;
69 }
70 
71 void
72 physical_SetDeviceList(struct physical *p, int argc, const char *const *argv)
73 {
74   int f, pos;
75 
76   p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0';
77   for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) {
78     if (pos)
79       p->cfg.devlist[pos++] = ' ';
80     strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1);
81     pos += strlen(p->cfg.devlist + pos);
82   }
83 }
84 
85 
86 int
87 physical_SetSpeed(struct physical *phys, int speed) {
88    if (IntToSpeed(speed) != B0) {
89       phys->cfg.speed = speed;
90       return 1;
91    } else {
92       return 0;
93    }
94 }
95 
96 void
97 physical_SetSync(struct physical *phys) {
98    phys->cfg.speed = 0;
99 }
100 
101 
102 int
103 physical_SetRtsCts(struct physical *phys, int enable) {
104    phys->cfg.rts_cts = enable ? 1 : 0;
105    return 1;
106 }
107 
108 /* Encapsulation for a read on the FD.  Avoids some exposure, and
109    concentrates control. */
110 ssize_t
111 physical_Read(struct physical *phys, void *buf, size_t nbytes) {
112    return read(phys->fd, buf, nbytes);
113 }
114 
115 ssize_t
116 physical_Write(struct physical *phys, const void *buf, size_t nbytes) {
117    return write(phys->fd, buf, nbytes);
118 }
119 
120 int
121 physical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e,
122                    int *n, int force)
123 {
124   struct physical *p = descriptor2physical(d);
125   int sets;
126 
127   sets = 0;
128   if (p->fd >= 0) {
129     if (r) {
130       FD_SET(p->fd, r);
131       log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd);
132       sets++;
133     }
134     if (e) {
135       FD_SET(p->fd, e);
136       log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd);
137       sets++;
138     }
139     if (w && (force || link_QueueLen(&p->link) || p->out)) {
140       FD_SET(p->fd, w);
141       log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd);
142       sets++;
143     }
144     if (sets && *n < p->fd + 1)
145       *n = p->fd + 1;
146   }
147 
148   return sets;
149 }
150 
151 int
152 physical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e)
153 {
154   int sets;
155 
156   sets = 0;
157   if (p->fd >= 0) {
158     if (r && FD_ISSET(p->fd, r)) {
159       FD_CLR(p->fd, r);
160       log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd);
161       sets++;
162     }
163     if (e && FD_ISSET(p->fd, e)) {
164       FD_CLR(p->fd, e);
165       log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd);
166       sets++;
167     }
168     if (w && FD_ISSET(p->fd, w)) {
169       FD_CLR(p->fd, w);
170       log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd);
171       sets++;
172     }
173   }
174 
175   return sets;
176 }
177 
178 int
179 physical_IsSet(struct descriptor *d, const fd_set *fdset)
180 {
181   struct physical *p = descriptor2physical(d);
182   return p->fd >= 0 && FD_ISSET(p->fd, fdset);
183 }
184 
185 void
186 physical_Login(struct physical *phys, const char *name)
187 {
188   if (phys->type == PHYS_DIRECT && physical_IsATTY(phys)) {
189     if (phys->Utmp)
190       log_Printf(LogERROR, "Oops, already logged in on %s\n", phys->name.base);
191     else {
192       struct utmp ut;
193       const char *connstr;
194 
195       memset(&ut, 0, sizeof ut);
196       time(&ut.ut_time);
197       strncpy(ut.ut_name, name, sizeof ut.ut_name);
198       strncpy(ut.ut_line, phys->name.base, sizeof ut.ut_line);
199       if ((connstr = getenv("CONNECT")))
200         /* mgetty sets this to the connection speed */
201         strncpy(ut.ut_host, connstr, sizeof ut.ut_host);
202       ID0login(&ut);
203       phys->Utmp = 1;
204     }
205   }
206 }
207 
208 void
209 physical_Logout(struct physical *phys)
210 {
211   if (phys->Utmp) {
212     ID0logout(phys->name.base);
213     phys->Utmp = 0;
214   }
215 }
216 
217 int
218 physical_SetMode(struct physical *p, int mode)
219 {
220   if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) ||
221        mode & (PHYS_DIRECT|PHYS_DEDICATED)) &&
222       (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) {
223     log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name,
224                mode2Nam(p->type), mode2Nam(mode));
225     return 0;
226   }
227   p->type = mode;
228   return 1;
229 }
230 
231 void
232 physical_DeleteQueue(struct physical *p)
233 {
234   if (p->out) {
235     mbuf_Free(p->out);
236     p->out = NULL;
237   }
238   link_DeleteQueue(&p->link);
239 }
240