]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/rfcnb-util.c
363d4533b3acd1f234fc94f090e8db7c74edcedc
2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
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.
9 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
12 * RFCNB Utility Routines ...
14 * Copyright (C) Richard Sharpe 1996
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.
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.
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.
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"
41 #include <arpa/inet.h>
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 ..."
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> */
71 RFCNB_CvtPad_Name(char *name1
, char *name2
)
78 for (i
= 0; i
< 16; i
++) {
83 c2
= 'A'; /* CA is a space */
88 c1
= (char) ((int) c
/ 16 + (int) 'A');
89 c2
= (char) ((int) c
% 16 + (int) 'A');
93 name2
[i
* 2 + 1] = c2
;
97 name2
[32] = 0; /* Put in the nll ... */
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.
105 * This routine assumes that AName is 16 bytes long and that NBName has
106 * space for 32 chars, so be careful ...
109 RFCNB_AName_To_NBName(char *AName
, char *NBName
)
114 for (i
= 0; i
< 16; i
++) {
118 c1
= (char) ((c
>> 4) + 'A');
119 c2
= (char) ((c
& 0xF) + 'A');
122 NBName
[i
* 2 + 1] = c2
;
125 NBName
[32] = 0; /* Put in a null */
128 /* Do the reverse of the above ... */
130 RFCNB_NBName_To_AName(char *NBName
, char *AName
)
135 for (i
= 0; i
< 16; i
++) {
138 c2
= NBName
[i
* 2 + 1];
140 c
= (char) (((int) c1
- (int) 'A') * 16 + ((int) c2
- (int) 'A'));
146 AName
[i
] = 0; /* Put a null on the end ... */
149 /* Print a string of bytes in HEX etc */
151 RFCNB_Print_Hex(FILE * fd
, struct RFCNB_Pkt
*pkt
, int Offset
, int Len
)
153 char c1
, c2
, outbuf1
[33];
156 struct RFCNB_Pkt
*pkt_ptr
= pkt
;
157 static char Hex_List
[17] = "0123456789ABCDEF";
161 /* We only want to print as much as sepcified in Len */
163 while (pkt_ptr
!= NULL
) {
166 i
< ((Len
> (pkt_ptr
->len
) ? pkt_ptr
->len
: Len
) - Offset
);
169 c
= pkt_ptr
->data
[i
+ Offset
];
170 c1
= Hex_List
[c
>> 4];
171 c2
= Hex_List
[c
& 0xF];
176 if (j
== 32) { /* Print and reset */
178 fprintf(fd
, " %s\n", outbuf1
);
184 Len
= Len
- pkt_ptr
->len
; /* Reduce amount by this much */
185 pkt_ptr
= pkt_ptr
->next
;
189 /* Print last lot in the buffer ... */
194 fprintf(fd
, " %s\n", outbuf1
);
200 /* Get a packet of size n */
202 RFCNB_Alloc_Pkt(int n
) {
205 if ((pkt
= (struct RFCNB_Pkt
*) malloc(sizeof(struct RFCNB_Pkt
))) == NULL
) {
207 RFCNB_errno
= RFCNBE_NoSpace
;
208 RFCNB_saved_errno
= errno
;
218 if ((pkt
->data
= (char *) malloc(n
)) == NULL
) {
220 RFCNB_errno
= RFCNBE_NoSpace
;
221 RFCNB_saved_errno
= errno
;
229 /* Free up a packet */
231 RFCNB_Free_Pkt(struct RFCNB_Pkt
*pkt
)
233 struct RFCNB_Pkt
*pkt_next
;
236 while (pkt
!= NULL
) {
238 pkt_next
= pkt
->next
;
240 data_ptr
= pkt
->data
;
242 if (data_ptr
!= NULL
)
252 /* Print an RFCNB packet */
254 RFCNB_Print_Pkt(FILE * fd
, char *dirn
, struct RFCNB_Pkt
*pkt
, int len
)
258 /* We assume that the first fragment is the RFCNB Header */
259 /* We should loop through the fragments printing them out */
261 fprintf(fd
, "RFCNB Pkt %s:", dirn
);
263 switch (RFCNB_Pkt_Type(pkt
->data
)) {
265 case RFCNB_SESSION_MESSAGE
:
267 fprintf(fd
, "SESSION MESSAGE: Length = %i\n", RFCNB_Pkt_Len(pkt
->data
));
268 RFCNB_Print_Hex(fd
, pkt
, RFCNB_Pkt_Hdr_Len
,
269 #ifdef RFCNB_PRINT_DATA
270 RFCNB_Pkt_Len(pkt
->data
) - RFCNB_Pkt_Hdr_Len
);
275 if (Prot_Print_Routine
) { /* Print the rest of the packet */
277 Prot_Print_Routine(fd
, strcmp(dirn
, "sent"), pkt
, RFCNB_Pkt_Hdr_Len
,
278 RFCNB_Pkt_Len(pkt
->data
) - RFCNB_Pkt_Hdr_Len
);
283 case RFCNB_SESSION_REQUEST
:
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
);
294 case RFCNB_SESSION_ACK
:
296 fprintf(fd
, "RFCNB SESSION ACK: Length = %i\n",
297 RFCNB_Pkt_Len(pkt
->data
));
301 case RFCNB_SESSION_REJ
:
302 fprintf(fd
, "RFCNB SESSION REJECT: Length = %i\n",
303 RFCNB_Pkt_Len(pkt
->data
));
305 if (RFCNB_Pkt_Len(pkt
->data
) < 1) {
306 fprintf(fd
, " Protocol Error, short Reject packet!\n");
308 fprintf(fd
, " Error = %x\n", CVAL(pkt
->data
, RFCNB_Pkt_Error_Offset
));
313 case RFCNB_SESSION_RETARGET
:
315 fprintf(fd
, "RFCNB SESSION RETARGET: Length = %i\n",
316 RFCNB_Pkt_Len(pkt
->data
));
318 /* Print out the IP address etc and the port? */
322 case RFCNB_SESSION_KEEP_ALIVE
:
324 fprintf(fd
, "RFCNB SESSION KEEP ALIVE: Length = %i\n",
325 RFCNB_Pkt_Len(pkt
->data
));
334 /* Resolve a name into an address */
336 RFCNB_Name_To_IP(char *host
, struct in_addr
*Dest_IP
)
338 int addr
; /* Assumes IP4, 32 bit network addresses */
341 /* Use inet_addr to try to convert the address */
343 if ((addr
= inet_addr(host
)) == INADDR_NONE
) { /* Oh well, a good try :-) */
345 /* Now try a name look up with gethostbyname */
347 if ((hp
= gethostbyname(host
)) == NULL
) { /* Not in DNS */
349 /* Try NetBIOS name lookup, how the hell do we do that? */
351 RFCNB_errno
= RFCNBE_BadName
; /* Is this right? */
352 RFCNB_saved_errno
= errno
;
355 } else { /* We got a name */
357 memcpy((void *) Dest_IP
, (void *) hp
->h_addr_list
[0], sizeof(struct in_addr
));
360 } else { /* It was an IP address */
362 memcpy((void *) Dest_IP
, (void *) &addr
, sizeof(struct in_addr
));
369 /* Disconnect the TCP connection to the server */
376 /* If we want to do error recovery, here is where we put it */
381 /* Connect to the server specified in the IP address.
382 * Not sure how to handle socket options etc. */
384 RFCNB_IP_Connect(struct in_addr Dest_IP
, int port
)
386 struct sockaddr_in Socket
;
389 /* Create a socket */
391 if ((fd
= socket(PF_INET
, SOCK_STREAM
, 0)) < 0) { /* Handle the error */
393 RFCNB_errno
= RFCNBE_BadSocket
;
394 RFCNB_saved_errno
= errno
;
397 memset((char *) &Socket
, 0, sizeof(Socket
));
398 memcpy((char *) &Socket
.sin_addr
, (char *) &Dest_IP
, sizeof(Dest_IP
));
400 Socket
.sin_port
= htons(port
);
401 Socket
.sin_family
= PF_INET
;
403 /* Now connect to the destination */
405 if (connect(fd
, (struct sockaddr
*) &Socket
, sizeof(Socket
)) < 0) { /* Error */
408 RFCNB_errno
= RFCNBE_ConnectFailed
;
409 RFCNB_saved_errno
= errno
;
415 /* handle the details of establishing the RFCNB session with remote
419 RFCNB_Session_Req(struct RFCNB_Con
*con
,
423 struct in_addr
*Dest_IP
,
428 /* Response packet should be no more than 9 bytes, make 16 jic */
430 // char ln1[16], ln2[16], n1[32], n2[32];
433 struct RFCNB_Pkt
*pkt
, res_pkt
;
436 /* We build and send the session request, then read the response */
438 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Sess_Len
);
441 return (RFCNBE_Bad
); /* Leave the error that RFCNB_Alloc_Pkt gives) */
443 sess_pkt
= pkt
->data
; /* Get pointer to packet proper */
445 sess_pkt
[RFCNB_Pkt_Type_Offset
] = RFCNB_SESSION_REQUEST
;
446 RFCNB_Put_Pkt_Len(sess_pkt
, RFCNB_Pkt_Sess_Len
- RFCNB_Pkt_Hdr_Len
);
447 sess_pkt
[RFCNB_Pkt_N1Len_Offset
] = 32;
448 sess_pkt
[RFCNB_Pkt_N2Len_Offset
] = 32;
450 RFCNB_CvtPad_Name(Called_Name
, (sess_pkt
+ RFCNB_Pkt_Called_Offset
));
451 RFCNB_CvtPad_Name(Calling_Name
, (sess_pkt
+ RFCNB_Pkt_Calling_Offset
));
453 /* Now send the packet */
456 fprintf(stderr
, "Sending packet: ");
459 if ((len
= RFCNB_Put_Pkt(con
, pkt
, RFCNB_Pkt_Sess_Len
)) < 0) {
461 return (RFCNBE_Bad
); /* Should be able to write that lot ... */
465 fprintf(stderr
, "Getting packet.\n");
469 res_pkt
.len
= sizeof(resp
);
472 if ((len
= RFCNB_Get_Pkt(con
, &res_pkt
, sizeof(resp
))) < 0) {
477 /* Now analyze the packet ... */
479 switch (RFCNB_Pkt_Type(resp
)) {
481 case RFCNB_SESSION_REJ
: /* Didnt like us ... too bad */
483 /* Why did we get rejected ? */
485 switch (CVAL(resp
, RFCNB_Pkt_Error_Offset
)) {
488 RFCNB_errno
= RFCNBE_CallRejNLOCN
;
491 RFCNB_errno
= RFCNBE_CallRejNLFCN
;
494 RFCNB_errno
= RFCNBE_CallRejCNNP
;
497 RFCNB_errno
= RFCNBE_CallRejInfRes
;
500 RFCNB_errno
= RFCNBE_CallRejUnSpec
;
503 RFCNB_errno
= RFCNBE_ProtErr
;
507 result
= (RFCNBE_Bad
);
510 case RFCNB_SESSION_ACK
: /* Got what we wanted ... */
515 case RFCNB_SESSION_RETARGET
: /* Go elsewhere */
517 *redirect
= TRUE
; /* Copy port and ip addr */
519 memcpy(Dest_IP
, (resp
+ RFCNB_Pkt_IP_Offset
), sizeof(struct in_addr
));
520 *port
= SVAL(resp
, RFCNB_Pkt_Port_Offset
);
525 default: /* A protocol error */
527 RFCNB_errno
= RFCNBE_ProtErr
;
528 result
= (RFCNBE_Bad
);