rfcnb-util.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
10  *
11  * Version 1.0
12  * RFCNB Utility Routines ...
13  *
14  * Copyright (C) Richard Sharpe 1996
15  */
16 
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31  */
32 
33 #include "squid.h"
34 #include "rfcnb/rfcnb-io.h"
35 #include "rfcnb/rfcnb-priv.h"
36 #include "rfcnb/rfcnb-util.h"
37 #include "rfcnb/rfcnb.h"
38 #include "rfcnb/std-includes.h"
39 
40 #if HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
42 #endif
43 #if HAVE_STRING_H
44 #include <string.h>
45 #endif
46 
47 const char *RFCNB_Error_Strings[] = {
48  "RFCNBE_OK: Routine completed successfully.",
49  "RFCNBE_NoSpace: No space available for a malloc call.",
50  "RFCNBE_BadName: NetBIOS name could not be translated to IP address.",
51  "RFCNBE_BadRead: Read system call returned an error. Check errno.",
52  "RFCNBE_BadWrite: Write system call returned an error. Check errno.",
53  "RFCNBE_ProtErr: A protocol error has occurred.",
54  "RFCNBE_ConGone: Connection dropped during a read or write system call.",
55  "RFCNBE_BadHandle: Bad connection handle passed.",
56  "RFCNBE_BadSocket: Problems creating socket.",
57  "RFCNBE_ConnectFailed: Connection failed. See errno.",
58  "RFCNBE_CallRejNLOCN: Call rejected. Not listening on called name.",
59  "RFCNBE_CallRejNLFCN: Call rejected. Not listening for called name.",
60  "RFCNBE_CallRejCNNP: Call rejected. Called name not present.",
61  "RFCNBE_CallRejInfRes: Call rejected. Name present, but insufficient resources.",
62  "RFCNBE_CallRejUnSpec: Call rejected. Unspecified error.",
63  "RFCNBE_BadParam: Bad parameters passed to a routine.",
64  "RFCNBE_Timeout: IO Operation timed out ..."
65 };
66 
67 /* Convert name and pad to 16 chars as needed */
68 /* Name 1 is a C string with null termination, name 2 may not be */
69 /* If SysName is true, then put a <00> on end, else space> */
70 void
71 RFCNB_CvtPad_Name(char *name1, char *name2)
72 {
73  char c, c1, c2;
74  int i, len;
75 
76  len = strlen(name1);
77 
78  for (i = 0; i < 16; i++) {
79 
80  if (i >= len) {
81 
82  c1 = 'C';
83  c2 = 'A'; /* CA is a space */
84 
85  } else {
86 
87  c = name1[i];
88  c1 = (char) ((int) c / 16 + (int) 'A');
89  c2 = (char) ((int) c % 16 + (int) 'A');
90  }
91 
92  name2[i * 2] = c1;
93  name2[i * 2 + 1] = c2;
94 
95  }
96 
97  name2[32] = 0; /* Put in the nll ... */
98 
99 }
100 
101 /* Converts an Ascii NB Name (16 chars) to an RFCNB Name (32 chars)
102  * Uses the encoding in RFC1001. Each nibble of byte is added to 'A'
103  * to produce the next byte in the name.
104  *
105  * This routine assumes that AName is 16 bytes long and that NBName has
106  * space for 32 chars, so be careful ...
107  */
108 void
109 RFCNB_AName_To_NBName(char *AName, char *NBName)
110 {
111  char c, c1, c2;
112  int i;
113 
114  for (i = 0; i < 16; i++) {
115 
116  c = AName[i];
117 
118  c1 = (char) ((c >> 4) + 'A');
119  c2 = (char) ((c & 0xF) + 'A');
120 
121  NBName[i * 2] = c1;
122  NBName[i * 2 + 1] = c2;
123  }
124 
125  NBName[32] = 0; /* Put in a null */
126 }
127 
128 /* Do the reverse of the above ... */
129 void
130 RFCNB_NBName_To_AName(char *NBName, char *AName)
131 {
132  char c, c1, c2;
133  int i;
134 
135  for (i = 0; i < 16; i++) {
136 
137  c1 = NBName[i * 2];
138  c2 = NBName[i * 2 + 1];
139 
140  c = (char) (((int) c1 - (int) 'A') * 16 + ((int) c2 - (int) 'A'));
141 
142  AName[i] = c;
143 
144  }
145 
146  AName[i] = 0; /* Put a null on the end ... */
147 }
148 
149 /* Print a string of bytes in HEX etc */
150 void
151 RFCNB_Print_Hex(FILE * fd, struct RFCNB_Pkt *pkt, int Offset, int Len)
152 {
153  char c1, c2, outbuf1[33];
154  unsigned char c;
155  int i, j;
156  struct RFCNB_Pkt *pkt_ptr = pkt;
157  static char Hex_List[17] = "0123456789ABCDEF";
158 
159  j = 0;
160 
161  /* We only want to print as much as specified in Len */
162 
163  while (pkt_ptr != NULL) {
164 
165  for (i = 0;
166  i < ((Len > (pkt_ptr->len) ? pkt_ptr->len : Len) - Offset);
167  i++) {
168 
169  c = pkt_ptr->data[i + Offset];
170  c1 = Hex_List[c >> 4];
171  c2 = Hex_List[c & 0xF];
172 
173  outbuf1[j++] = c1;
174  outbuf1[j++] = c2;
175 
176  if (j == 32) { /* Print and reset */
177  outbuf1[j] = 0;
178  fprintf(fd, " %s\n", outbuf1);
179  j = 0;
180  }
181  }
182 
183  Offset = 0;
184  Len = Len - pkt_ptr->len; /* Reduce amount by this much */
185  pkt_ptr = pkt_ptr->next;
186 
187  }
188 
189  /* Print last lot in the buffer ... */
190 
191  if (j > 0) {
192 
193  outbuf1[j] = 0;
194  fprintf(fd, " %s\n", outbuf1);
195 
196  }
197  fprintf(fd, "\n");
198 }
199 
200 /* Get a packet of size n */
201 struct RFCNB_Pkt *
203  RFCNB_Pkt *pkt;
204 
205  if ((pkt = (struct RFCNB_Pkt *) malloc(sizeof(struct RFCNB_Pkt))) == NULL) {
206 
208  RFCNB_saved_errno = errno;
209  return (NULL);
210 
211  }
212  pkt->next = NULL;
213  pkt->len = n;
214 
215  if (n == 0)
216  return (pkt);
217 
218  if ((pkt->data = (char *) malloc(n)) == NULL) {
219 
221  RFCNB_saved_errno = errno;
222  free(pkt);
223  return (NULL);
224 
225  }
226  return (pkt);
227 }
228 
229 /* Free up a packet */
230 void
232 {
233  struct RFCNB_Pkt *pkt_next;
234  char *data_ptr;
235 
236  while (pkt != NULL) {
237 
238  pkt_next = pkt->next;
239 
240  data_ptr = pkt->data;
241 
242  if (data_ptr != NULL)
243  free(data_ptr);
244 
245  free(pkt);
246 
247  pkt = pkt_next;
248 
249  }
250 }
251 
252 /* Print an RFCNB packet */
253 void
254 RFCNB_Print_Pkt(FILE * fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
255 {
256  char lname[17];
257 
258  /* We assume that the first fragment is the RFCNB Header */
259  /* We should loop through the fragments printing them out */
260 
261  fprintf(fd, "RFCNB Pkt %s:", dirn);
262 
263  switch (RFCNB_Pkt_Type(pkt->data)) {
264 
266 
267  fprintf(fd, "SESSION MESSAGE: Length = %i\n", RFCNB_Pkt_Len(pkt->data));
269 #ifdef RFCNB_PRINT_DATA
271 #else
272  40);
273 #endif
274 
275  if (Prot_Print_Routine) { /* Print the rest of the packet */
276 
277  Prot_Print_Routine(fd, strcmp(dirn, "sent"), pkt, RFCNB_Pkt_Hdr_Len,
279 
280  }
281  break;
282 
284 
285  fprintf(fd, "SESSION REQUEST: Length = %i\n",
286  RFCNB_Pkt_Len(pkt->data));
287  RFCNB_NBName_To_AName((char *) (pkt->data + RFCNB_Pkt_Called_Offset), lname);
288  fprintf(fd, " Called Name: %s\n", lname);
289  RFCNB_NBName_To_AName((char *) (pkt->data + RFCNB_Pkt_Calling_Offset), lname);
290  fprintf(fd, " Calling Name: %s\n", lname);
291 
292  break;
293 
294  case RFCNB_SESSION_ACK:
295 
296  fprintf(fd, "RFCNB SESSION ACK: Length = %i\n",
297  RFCNB_Pkt_Len(pkt->data));
298 
299  break;
300 
301  case RFCNB_SESSION_REJ:
302  fprintf(fd, "RFCNB SESSION REJECT: Length = %i\n",
303  RFCNB_Pkt_Len(pkt->data));
304 
305  if (RFCNB_Pkt_Len(pkt->data) < 1) {
306  fprintf(fd, " Protocol Error, short Reject packet!\n");
307  } else {
308  fprintf(fd, " Error = %x\n", CVAL(pkt->data, RFCNB_Pkt_Error_Offset));
309  }
310 
311  break;
312 
314 
315  fprintf(fd, "RFCNB SESSION RETARGET: Length = %i\n",
316  RFCNB_Pkt_Len(pkt->data));
317 
318  /* Print out the IP address etc and the port? */
319 
320  break;
321 
323 
324  fprintf(fd, "RFCNB SESSION KEEP ALIVE: Length = %i\n",
325  RFCNB_Pkt_Len(pkt->data));
326  break;
327 
328  default:
329 
330  break;
331  }
332 }
333 
334 /* Resolve a name into an address */
335 int
336 RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
337 {
338  int addr; /* Assumes IP4, 32 bit network addresses */
339  struct hostent *hp;
340 
341  /* Use inet_addr to try to convert the address */
342 
343  if ((addr = inet_addr(host)) == INADDR_NONE) { /* Oh well, a good try :-) */
344 
345  /* Now try a name look up with gethostbyname */
346 
347  if ((hp = gethostbyname(host)) == NULL) { /* Not in DNS */
348 
349  /* Try NetBIOS name lookup, how the hell do we do that? */
350 
351  RFCNB_errno = RFCNBE_BadName; /* Is this right? */
352  RFCNB_saved_errno = errno;
353  return (RFCNBE_Bad);
354 
355  } else { /* We got a name */
356 
357  memcpy((void *) Dest_IP, (void *) hp->h_addr_list[0], sizeof(struct in_addr));
358 
359  }
360  } else { /* It was an IP address */
361 
362  memcpy((void *) Dest_IP, (void *) &addr, sizeof(struct in_addr));
363 
364  }
365 
366  return 0;
367 }
368 
369 /* Disconnect the TCP connection to the server */
370 int
371 RFCNB_Close(int fd)
372 {
373 
374  close(fd);
375 
376  /* If we want to do error recovery, here is where we put it */
377 
378  return 0;
379 }
380 
381 /* Connect to the server specified in the IP address.
382  * Not sure how to handle socket options etc. */
383 int
384 RFCNB_IP_Connect(struct in_addr Dest_IP, int port)
385 {
386  struct sockaddr_in Socket;
387  int fd;
388 
389  /* Create a socket */
390 
391  if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { /* Handle the error */
392 
394  RFCNB_saved_errno = errno;
395  return (RFCNBE_Bad);
396  }
397  memset((char *) &Socket, 0, sizeof(Socket));
398  memcpy((char *) &Socket.sin_addr, (char *) &Dest_IP, sizeof(Dest_IP));
399 
400  Socket.sin_port = htons(port);
401  Socket.sin_family = PF_INET;
402 
403  /* Now connect to the destination */
404 
405  if (connect(fd, (struct sockaddr *) &Socket, sizeof(Socket)) < 0) { /* Error */
406 
407  close(fd);
409  RFCNB_saved_errno = errno;
410  return (RFCNBE_Bad);
411  }
412  return (fd);
413 }
414 
415 /* handle the details of establishing the RFCNB session with remote
416  * end
417  */
418 int
420  char *Called_Name,
421  char *Calling_Name,
422  BOOL * redirect,
423  struct in_addr *Dest_IP,
424  int *port)
425 {
426  char *sess_pkt;
427 
428  /* Response packet should be no more than 9 bytes, make 16 jic */
429 
430 // char ln1[16], ln2[16], n1[32], n2[32];
431  char resp[16];
432  int len;
433  struct RFCNB_Pkt *pkt, res_pkt;
434  int result = 0;
435 
436  /* We build and send the session request, then read the response */
437 
439 
440  if (pkt == NULL) {
441  return (RFCNBE_Bad); /* Leave the error that RFCNB_Alloc_Pkt gives) */
442  }
443  sess_pkt = pkt->data; /* Get pointer to packet proper */
444 
447  sess_pkt[RFCNB_Pkt_N1Len_Offset] = 32;
448  sess_pkt[RFCNB_Pkt_N2Len_Offset] = 32;
449 
450  RFCNB_CvtPad_Name(Called_Name, (sess_pkt + RFCNB_Pkt_Called_Offset));
451  RFCNB_CvtPad_Name(Calling_Name, (sess_pkt + RFCNB_Pkt_Calling_Offset));
452 
453  /* Now send the packet */
454 
455 #ifdef RFCNB_DEBUG
456  fprintf(stderr, "Sending packet: ");
457 #endif
458 
459  if ((len = RFCNB_Put_Pkt(con, pkt, RFCNB_Pkt_Sess_Len)) < 0) {
460  RFCNB_Free_Pkt(pkt);
461  return (RFCNBE_Bad); /* Should be able to write that lot ... */
462 
463  }
464 #ifdef RFCNB_DEBUG
465  fprintf(stderr, "Getting packet.\n");
466 #endif
467 
468  res_pkt.data = resp;
469  res_pkt.len = sizeof(resp);
470  res_pkt.next = NULL;
471 
472  if ((len = RFCNB_Get_Pkt(con, &res_pkt, sizeof(resp))) < 0) {
473  RFCNB_Free_Pkt(pkt);
474  return (RFCNBE_Bad);
475 
476  }
477  /* Now analyze the packet ... */
478 
479  switch (RFCNB_Pkt_Type(resp)) {
480 
481  case RFCNB_SESSION_REJ: /* Didn't like us ... too bad */
482 
483  /* Why did we get rejected ? */
484 
485  switch (CVAL(resp, RFCNB_Pkt_Error_Offset)) {
486 
487  case 0x80:
489  break;
490  case 0x81:
492  break;
493  case 0x82:
495  break;
496  case 0x83:
498  break;
499  case 0x8F:
501  break;
502  default:
504  break;
505  }
506 
507  result = (RFCNBE_Bad);
508  break;
509 
510  case RFCNB_SESSION_ACK: /* Got what we wanted ... */
511 
512  result = (0);
513  break;
514 
515  case RFCNB_SESSION_RETARGET: /* Go elsewhere */
516 
517  *redirect = TRUE; /* Copy port and ip addr */
518 
519  memcpy(Dest_IP, (resp + RFCNB_Pkt_IP_Offset), sizeof(struct in_addr));
520  *port = SVAL(resp, RFCNB_Pkt_Port_Offset);
521 
522  result = (0);
523  break;
524 
525  default: /* A protocol error */
526 
528  result = (RFCNBE_Bad);
529  break;
530  }
531 
532  RFCNB_Free_Pkt(pkt);
533  return result;
534 }
535 
#define RFCNB_Pkt_IP_Offset
Definition: rfcnb-priv.h:109
#define RFCNB_Pkt_Type(p)
Definition: rfcnb-priv.h:122
#define RFCNBE_ProtErr
Definition: rfcnb-error.h:51
#define RFCNB_SESSION_RETARGET
Definition: rfcnb-priv.h:64
#define RFCNB_Pkt_Sess_Len
Definition: rfcnb-priv.h:98
#define RFCNBE_ConnectFailed
Definition: rfcnb-error.h:55
void RFCNB_Print_Hex(FILE *fd, struct RFCNB_Pkt *pkt, int Offset, int Len)
Definition: rfcnb-util.c:151
#define RFCNB_SESSION_MESSAGE
Definition: rfcnb-priv.h:60
#define RFCNB_Pkt_Calling_Offset
Definition: rfcnb-priv.h:107
void RFCNB_CvtPad_Name(char *name1, char *name2)
Definition: rfcnb-util.c:71
#define RFCNBE_BadName
Definition: rfcnb-error.h:48
static int port
Definition: ldap_backend.cc:70
#define RFCNB_Pkt_N1Len_Offset
Definition: rfcnb-priv.h:104
#define RFCNBE_CallRejUnSpec
Definition: rfcnb-error.h:60
#define INADDR_NONE
Definition: std-includes.h:61
#define RFCNB_Pkt_Len(p)
Definition: rfcnb-priv.h:115
#define RFCNBE_BadSocket
Definition: rfcnb-error.h:54
#define NULL
Definition: types.h:145
#define RFCNB_Pkt_Hdr_Len
Definition: rfcnb-priv.h:97
void RFCNB_NBName_To_AName(char *NBName, char *AName)
Definition: rfcnb-util.c:130
#define RFCNB_SESSION_ACK
Definition: rfcnb-priv.h:62
void RFCNB_Print_Pkt(FILE *fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-util.c:254
int RFCNB_IP_Connect(struct in_addr Dest_IP, int port)
Definition: rfcnb-util.c:384
#define CVAL(buf, pos)
Definition: byteorder.h:52
#define RFCNB_Pkt_Type_Offset
Definition: rfcnb-priv.h:101
#define RFCNB_SESSION_REQUEST
Definition: rfcnb-priv.h:61
char * data
Definition: rfcnb-common.h:44
#define RFCNBE_Bad
Definition: rfcnb-error.h:42
#define RFCNB_Put_Pkt_Len(p, v)
Definition: rfcnb-priv.h:118
#define RFCNB_Pkt_N2Len_Offset
Definition: rfcnb-priv.h:106
#define TRUE
Definition: std-includes.h:55
const char * RFCNB_Error_Strings[]
Definition: rfcnb-util.c:47
#define RFCNBE_CallRejNLFCN
Definition: rfcnb-error.h:57
int RFCNB_errno
Definition: session.c:35
#define RFCNB_Pkt_Called_Offset
Definition: rfcnb-priv.h:105
int RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
Definition: rfcnb-util.c:336
#define RFCNBE_CallRejNLOCN
Definition: rfcnb-error.h:56
int RFCNB_saved_errno
Definition: session.c:36
#define RFCNBE_CallRejCNNP
Definition: rfcnb-error.h:58
#define RFCNB_Pkt_Port_Offset
Definition: rfcnb-priv.h:110
int RFCNB_Session_Req(struct RFCNB_Con *con, char *Called_Name, char *Calling_Name, BOOL *redirect, struct in_addr *Dest_IP, int *port)
Definition: rfcnb-util.c:419
void RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt)
Definition: rfcnb-util.c:231
#define RFCNB_SESSION_REJ
Definition: rfcnb-priv.h:63
#define SVAL(buf, pos)
Definition: byteorder.h:57
void RFCNB_AName_To_NBName(char *AName, char *NBName)
Definition: rfcnb-util.c:109
#define RFCNBE_CallRejInfRes
Definition: rfcnb-error.h:59
RFCNB_Prot_Print_Routine * Prot_Print_Routine
Definition: session.c:52
#define RFCNB_SESSION_KEEP_ALIVE
Definition: rfcnb-priv.h:65
int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-io.c:101
#define RFCNB_Pkt_Error_Offset
Definition: rfcnb-priv.h:108
#define RFCNBE_NoSpace
Definition: rfcnb-error.h:47
struct RFCNB_Pkt * next
Definition: rfcnb-common.h:46
#define BOOL
Definition: std-includes.h:38
int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-io.c:189
int RFCNB_Close(int fd)
Definition: rfcnb-util.c:371
int unsigned int
Definition: stub_fd.cc:19
struct RFCNB_Pkt * RFCNB_Alloc_Pkt(int n)
Definition: rfcnb-util.c:202

 

Introduction

Documentation

Support

Miscellaneous