]> git.saurik.com Git - apple/network_cmds.git/blob - rbootd.tproj/utils.c
network_cmds-85.tar.gz
[apple/network_cmds.git] / rbootd.tproj / utils.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1988, 1992 The University of Utah and the Center
26 * for Software Science (CSS).
27 * Copyright (c) 1992, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * This code is derived from software contributed to Berkeley by
31 * the Center for Software Science of the University of Utah Computer
32 * Science Department. CSS requests users of this software to return
33 * to css-dist@cs.utah.edu any improvements that they make and grant
34 * CSS redistribution rights.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)utils.c 8.2 (Berkeley) 2/22/94
65 *
66 * Utah $Hdr: utils.c 3.1 92/07/06$
67 * Author: Jeff Forys, University of Utah CSS
68 */
69
70 #ifndef lint
71 static char sccsid[] = "@(#)utils.c 8.2 (Berkeley) 2/22/94";
72 #endif /* not lint */
73
74 #include <sys/param.h>
75 #include <sys/time.h>
76
77 #include <fcntl.h>
78 #include <signal.h>
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <syslog.h>
83 #include <time.h>
84 #include <unistd.h>
85 #include "defs.h"
86
87 /*
88 ** DispPkt -- Display the contents of an RMPCONN packet.
89 **
90 ** Parameters:
91 ** rconn - packet to be displayed.
92 ** direct - direction packet is going (DIR_*).
93 **
94 ** Returns:
95 ** Nothing.
96 **
97 ** Side Effects:
98 ** None.
99 */
100 void
101 DispPkt(rconn, direct)
102 RMPCONN *rconn;
103 int direct;
104 {
105 static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u";
106 static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n";
107
108 struct tm *tmp;
109 register struct rmp_packet *rmp;
110 int i, omask;
111 u_int t;
112
113 /*
114 * Since we will be working with RmpConns as well as DbgFp, we
115 * must block signals that can affect either.
116 */
117 omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
118
119 if (DbgFp == NULL) { /* sanity */
120 (void) sigsetmask(omask);
121 return;
122 }
123
124 /* display direction packet is going using '>>>' or '<<<' */
125 fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
126
127 /* display packet timestamp */
128 tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
129 fprintf(DbgFp, "%02d:%02d:%02d.%06ld ", tmp->tm_hour, tmp->tm_min,
130 tmp->tm_sec, rconn->tstamp.tv_usec);
131
132 /* display src or dst addr and information about network interface */
133 fprintf(DbgFp, "Addr: %s Intf: %s\n", EnetStr(rconn), IntfName);
134
135 rmp = &rconn->rmp;
136
137 /* display IEEE 802.2 Logical Link Control header */
138 (void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
139 rmp->hp_llc.dsap, rmp->hp_llc.ssap, rmp->hp_llc.cntrl);
140
141 /* display HP extensions to 802.2 Logical Link Control header */
142 (void) fprintf(DbgFp, "\tHP Ext: DXSAP:%x SXSAP:%x\n",
143 rmp->hp_llc.dxsap, rmp->hp_llc.sxsap);
144
145 /*
146 * Display information about RMP packet using type field to
147 * determine what kind of packet this is.
148 */
149 switch(rmp->r_type) {
150 case RMP_BOOT_REQ: /* boot request */
151 (void) fprintf(DbgFp, "\tBoot Request:");
152 GETWORD(rmp->r_brq.rmp_seqno, t);
153 if (rmp->r_brq.rmp_session == RMP_PROBESID) {
154 if (WORDZE(rmp->r_brq.rmp_seqno))
155 fputs(" (Send Server ID)", DbgFp);
156 else
157 fprintf(DbgFp," (Send Filename #%u)",t);
158 }
159 (void) fputc('\n', DbgFp);
160 (void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
161 t, rmp->r_brq.rmp_session,
162 rmp->r_brq.rmp_version);
163 (void) fprintf(DbgFp, "\n\t\tMachine Type: ");
164 for (i = 0; i < RMP_MACHLEN; i++)
165 (void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
166 DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
167 break;
168 case RMP_BOOT_REPL: /* boot reply */
169 fprintf(DbgFp, "\tBoot Reply:\n");
170 GETWORD(rmp->r_brpl.rmp_seqno, t);
171 (void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
172 t, rmp->r_brpl.rmp_session,
173 rmp->r_brpl.rmp_version);
174 DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
175 break;
176 case RMP_READ_REQ: /* read request */
177 (void) fprintf(DbgFp, "\tRead Request:\n");
178 GETWORD(rmp->r_rrq.rmp_offset, t);
179 (void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
180 t, rmp->r_rrq.rmp_session);
181 (void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
182 rmp->r_rrq.rmp_size);
183 break;
184 case RMP_READ_REPL: /* read reply */
185 (void) fprintf(DbgFp, "\tRead Reply:\n");
186 GETWORD(rmp->r_rrpl.rmp_offset, t);
187 (void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
188 t, rmp->r_rrpl.rmp_session);
189 (void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n",
190 rconn->rmplen - RMPREADSIZE(0));
191 break;
192 case RMP_BOOT_DONE: /* boot complete */
193 (void) fprintf(DbgFp, "\tBoot Complete:\n");
194 (void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
195 rmp->r_done.rmp_retcode,
196 rmp->r_done.rmp_session);
197 break;
198 default: /* ??? */
199 (void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
200 rmp->r_type);
201 }
202 (void) fputc('\n', DbgFp);
203 (void) fflush(DbgFp);
204
205 (void) sigsetmask(omask); /* reset old signal mask */
206 }
207
208
209 /*
210 ** GetEtherAddr -- convert an RMP (Ethernet) address into a string.
211 **
212 ** An RMP BOOT packet has been received. Look at the type field
213 ** and process Boot Requests, Read Requests, and Boot Complete
214 ** packets. Any other type will be dropped with a warning msg.
215 **
216 ** Parameters:
217 ** addr - array of RMP_ADDRLEN bytes.
218 **
219 ** Returns:
220 ** Pointer to static string representation of `addr'.
221 **
222 ** Side Effects:
223 ** None.
224 **
225 ** Warnings:
226 ** - The return value points to a static buffer; it must
227 ** be copied if it's to be saved.
228 ** - For speed, we assume a u_char consists of 8 bits.
229 */
230 char *
231 GetEtherAddr(addr)
232 u_char *addr;
233 {
234 static char Hex[] = "0123456789abcdef";
235 static char etherstr[RMP_ADDRLEN*3];
236 register int i;
237 register char *cp1, *cp2;
238
239 /*
240 * For each byte in `addr', convert it to "<hexchar><hexchar>:".
241 * The last byte does not get a trailing `:' appended.
242 */
243 i = 0;
244 cp1 = (char *)addr;
245 cp2 = etherstr;
246 for(;;) {
247 *cp2++ = Hex[*cp1 >> 4 & 0xf];
248 *cp2++ = Hex[*cp1++ & 0xf];
249 if (++i == RMP_ADDRLEN)
250 break;
251 *cp2++ = ':';
252 }
253 *cp2 = '\0';
254
255 return(etherstr);
256 }
257
258
259 /*
260 ** DispFlnm -- Print a string of bytes to DbgFp (often, a file name).
261 **
262 ** Parameters:
263 ** size - number of bytes to print.
264 ** flnm - address of first byte.
265 **
266 ** Returns:
267 ** Nothing.
268 **
269 ** Side Effects:
270 ** - Characters are sent to `DbgFp'.
271 */
272 void
273 DspFlnm(size, flnm)
274 register u_int size;
275 register char *flnm;
276 {
277 register int i;
278
279 (void) fprintf(DbgFp, "\n\t\tFile Name (%d): <", size);
280 for (i = 0; i < size; i++)
281 (void) fputc(*flnm++, DbgFp);
282 (void) fputs(">\n", DbgFp);
283 }
284
285
286 /*
287 ** NewClient -- allocate memory for a new CLIENT.
288 **
289 ** Parameters:
290 ** addr - RMP (Ethernet) address of new client.
291 **
292 ** Returns:
293 ** Ptr to new CLIENT or NULL if we ran out of memory.
294 **
295 ** Side Effects:
296 ** - Memory will be malloc'd for the new CLIENT.
297 ** - If malloc() fails, a log message will be generated.
298 */
299 CLIENT *
300 NewClient(addr)
301 u_char *addr;
302 {
303 CLIENT *ctmp;
304
305 if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
306 syslog(LOG_ERR, "NewClient: out of memory (%s)",
307 GetEtherAddr(addr));
308 return(NULL);
309 }
310
311 bzero(ctmp, sizeof(CLIENT));
312 bcopy(addr, &ctmp->addr[0], RMP_ADDRLEN);
313 return(ctmp);
314 }
315
316 /*
317 ** FreeClient -- free linked list of Clients.
318 **
319 ** Parameters:
320 ** None.
321 **
322 ** Returns:
323 ** Nothing.
324 **
325 ** Side Effects:
326 ** - All malloc'd memory associated with the linked list of
327 ** CLIENTS will be free'd; `Clients' will be set to NULL.
328 **
329 ** Warnings:
330 ** - This routine must be called with SIGHUP blocked.
331 */
332 void
333 FreeClients()
334 {
335 register CLIENT *ctmp;
336
337 while (Clients != NULL) {
338 ctmp = Clients;
339 Clients = Clients->next;
340 FreeClient(ctmp);
341 }
342 }
343
344 /*
345 ** NewStr -- allocate memory for a character array.
346 **
347 ** Parameters:
348 ** str - null terminated character array.
349 **
350 ** Returns:
351 ** Ptr to new character array or NULL if we ran out of memory.
352 **
353 ** Side Effects:
354 ** - Memory will be malloc'd for the new character array.
355 ** - If malloc() fails, a log message will be generated.
356 */
357 char *
358 NewStr(str)
359 char *str;
360 {
361 char *stmp;
362
363 if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
364 syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
365 return(NULL);
366 }
367
368 (void) strcpy(stmp, str);
369 return(stmp);
370 }
371
372 /*
373 ** To save time, NewConn and FreeConn maintain a cache of one RMPCONN
374 ** in `LastFree' (defined below).
375 */
376
377 static RMPCONN *LastFree = NULL;
378
379 /*
380 ** NewConn -- allocate memory for a new RMPCONN connection.
381 **
382 ** Parameters:
383 ** rconn - initialization template for new connection.
384 **
385 ** Returns:
386 ** Ptr to new RMPCONN or NULL if we ran out of memory.
387 **
388 ** Side Effects:
389 ** - Memory may be malloc'd for the new RMPCONN (if not cached).
390 ** - If malloc() fails, a log message will be generated.
391 */
392 RMPCONN *
393 NewConn(rconn)
394 RMPCONN *rconn;
395 {
396 RMPCONN *rtmp;
397
398 if (LastFree == NULL) { /* nothing cached; make a new one */
399 if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
400 syslog(LOG_ERR, "NewConn: out of memory (%s)",
401 EnetStr(rconn));
402 return(NULL);
403 }
404 } else { /* use the cached RMPCONN */
405 rtmp = LastFree;
406 LastFree = NULL;
407 }
408
409 /*
410 * Copy template into `rtmp', init file descriptor to `-1' and
411 * set ptr to next elem NULL.
412 */
413 bcopy((char *)rconn, (char *)rtmp, sizeof(RMPCONN));
414 rtmp->bootfd = -1;
415 rtmp->next = NULL;
416
417 return(rtmp);
418 }
419
420 /*
421 ** FreeConn -- Free memory associated with an RMPCONN connection.
422 **
423 ** Parameters:
424 ** rtmp - ptr to RMPCONN to be free'd.
425 **
426 ** Returns:
427 ** Nothing.
428 **
429 ** Side Effects:
430 ** - Memory associated with `rtmp' may be free'd (or cached).
431 ** - File desc associated with `rtmp->bootfd' will be closed.
432 */
433 void
434 FreeConn(rtmp)
435 register RMPCONN *rtmp;
436 {
437 /*
438 * If the file descriptor is in use, close the file.
439 */
440 if (rtmp->bootfd >= 0) {
441 (void) close(rtmp->bootfd);
442 rtmp->bootfd = -1;
443 }
444
445 if (LastFree == NULL) /* cache for next time */
446 rtmp = LastFree;
447 else /* already one cached; free this one */
448 free((char *)rtmp);
449 }
450
451 /*
452 ** FreeConns -- free linked list of RMPCONN connections.
453 **
454 ** Parameters:
455 ** None.
456 **
457 ** Returns:
458 ** Nothing.
459 **
460 ** Side Effects:
461 ** - All malloc'd memory associated with the linked list of
462 ** connections will be free'd; `RmpConns' will be set to NULL.
463 ** - If LastFree is != NULL, it too will be free'd & NULL'd.
464 **
465 ** Warnings:
466 ** - This routine must be called with SIGHUP blocked.
467 */
468 void
469 FreeConns()
470 {
471 register RMPCONN *rtmp;
472
473 while (RmpConns != NULL) {
474 rtmp = RmpConns;
475 RmpConns = RmpConns->next;
476 FreeConn(rtmp);
477 }
478
479 if (LastFree != NULL) {
480 free((char *)LastFree);
481 LastFree = NULL;
482 }
483 }
484
485 /*
486 ** AddConn -- Add a connection to the linked list of connections.
487 **
488 ** Parameters:
489 ** rconn - connection to be added.
490 **
491 ** Returns:
492 ** Nothing.
493 **
494 ** Side Effects:
495 ** - RmpConn will point to new connection.
496 **
497 ** Warnings:
498 ** - This routine must be called with SIGHUP blocked.
499 */
500 void
501 AddConn(rconn)
502 register RMPCONN *rconn;
503 {
504 if (RmpConns != NULL)
505 rconn->next = RmpConns;
506 RmpConns = rconn;
507 }
508
509 /*
510 ** FindConn -- Find a connection in the linked list of connections.
511 **
512 ** We use the RMP (Ethernet) address as the basis for determining
513 ** if this is the same connection. According to the Remote Maint
514 ** Protocol, we can only have one connection with any machine.
515 **
516 ** Parameters:
517 ** rconn - connection to be found.
518 **
519 ** Returns:
520 ** Matching connection from linked list or NULL if not found.
521 **
522 ** Side Effects:
523 ** None.
524 **
525 ** Warnings:
526 ** - This routine must be called with SIGHUP blocked.
527 */
528 RMPCONN *
529 FindConn(rconn)
530 register RMPCONN *rconn;
531 {
532 register RMPCONN *rtmp;
533
534 for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
535 if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
536 (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
537 break;
538
539 return(rtmp);
540 }
541
542 /*
543 ** RemoveConn -- Remove a connection from the linked list of connections.
544 **
545 ** Parameters:
546 ** rconn - connection to be removed.
547 **
548 ** Returns:
549 ** Nothing.
550 **
551 ** Side Effects:
552 ** - If found, an RMPCONN will cease to exist and it will
553 ** be removed from the linked list.
554 **
555 ** Warnings:
556 ** - This routine must be called with SIGHUP blocked.
557 */
558 void
559 RemoveConn(rconn)
560 register RMPCONN *rconn;
561 {
562 register RMPCONN *thisrconn, *lastrconn;
563
564 if (RmpConns == rconn) { /* easy case */
565 RmpConns = RmpConns->next;
566 FreeConn(rconn);
567 } else { /* must traverse linked list */
568 lastrconn = RmpConns; /* set back ptr */
569 thisrconn = lastrconn->next; /* set current ptr */
570 while (thisrconn != NULL) {
571 if (rconn == thisrconn) { /* found it */
572 lastrconn->next = thisrconn->next;
573 FreeConn(thisrconn);
574 break;
575 }
576 lastrconn = thisrconn;
577 thisrconn = thisrconn->next;
578 }
579 }
580 }