"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* mod_ntlm file: $Id: rfcnb-util.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
2
3 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
4 *
5 * Version 1.0 RFCNB Utility Routines ...
6 *
7 * Copyright (C) Richard Sharpe 1996
8 *
9 */
10
11 /*
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. This program is distributed in the hope
16 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
17 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
18 * PURPOSE. See the GNU General Public License for more details. You
19 * should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #include <string.h>
24 #include <malloc.h>
25
26 #include "std-includes.h"
27 #include "rfcnb-priv.h"
28 #include "rfcnb-util.h"
29 #include "rfcnb-io.h"
30
31 /* Convert name and pad to 16 chars as needed. Name 1 is a C string
32 * with null termination, name 2 may not be. If SysName is true, then
33 * put a <00> on end, else space> */
34 static void
35 RFCNB_CvtPad_Name(char *name1, char *name2)
36 {
37 char c, c1, c2;
38 int i, len;
39
40 len = strlen(name1);
41 for (i = 0; i < 16; i++) {
42 if (i >= len) {
43 c1 = 'C';
44 c2 = 'A'; /* CA is a space */
45 } else {
46 c = name1[i];
47 c1 = (char) ((int) c / 16 + (int) 'A');
48 c2 = (char) ((int) c % 16 + (int) 'A');
49 }
50 name2[i * 2] = c1;
51 name2[i * 2 + 1] = c2;
52 }
53 name2[32] = 0; /* Put in the nll ... */
54 }
55
56 /* Get a packet of size n */
57 static struct RFCNB_Pkt *
58 RFCNB_Alloc_Pkt(int n)
59 {
60 RFCNB_Pkt *pkt;
61
62 if ((pkt = (struct RFCNB_Pkt *) malloc(
63 sizeof(struct RFCNB_Pkt))) == NULL) {
64 RFCNB_errno = RFCNBE_NoSpace;
65 RFCNB_saved_errno = errno;
66 return NULL;
67 }
68 pkt->next = NULL;
69 pkt->len = n;
70
71 if (n == 0)
72 return pkt;
73
74 if ((pkt->data = (char *) malloc(n)) == NULL) {
75 RFCNB_errno = RFCNBE_NoSpace;
76 RFCNB_saved_errno = errno;
77 free(pkt);
78 return (NULL);
79 }
80 return pkt;
81 }
82
83 /* Free up a packet */
84 static void
85 RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt)
86 {
87 struct RFCNB_Pkt *pkt_next;
88 char *data_ptr;
89
90 while (pkt != NULL) {
91 pkt_next = pkt->next;
92 data_ptr = pkt->data;
93 if (data_ptr != NULL)
94 free(data_ptr);
95 free(pkt);
96 pkt = pkt_next;
97 }
98 }
99
100 /* Resolve a name into an address */
101 static int
102 RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
103 {
104 int addr; /* Assumes IP4, 32 bit network addresses */
105 struct hostent *hp;
106
107 /* Use inet_addr to try to convert the address */
108 if ((addr = inet_addr(host)) == INADDR_NONE) { /* a good try :-) */
109 /* Now try a name look up with gethostbyname */
110 if ((hp = gethostbyname(host)) == NULL) { /* Not in DNS */
111 /* Try NetBIOS name lookup, how the hell do we do that? */
112 RFCNB_errno = RFCNBE_BadName; /* Is this right? */
113 RFCNB_saved_errno = errno;
114 return (RFCNBE_Bad);
115 } else { /* We got a name */
116 memcpy((void *) Dest_IP, (void *) hp->h_addr_list[0],
117 sizeof(struct in_addr));
118 }
119 } else { /* It was an IP address */
120 memcpy((void *) Dest_IP, (void *) &addr, sizeof(struct in_addr));
121 }
122 return 0;
123 }
124
125 /* Disconnect the TCP connection to the server */
126 static int
127 RFCNB_Close(int socket)
128 {
129 close(socket);
130 /* If we want to do error recovery, here is where we put it */
131 return 0;
132 }
133
134 /* Connect to the server specified in the IP address. Not sure how to
135 * handle socket options etc. */
136 static int
137 RFCNB_IP_Connect(struct in_addr Dest_IP, int port)
138 {
139 struct sockaddr_in Socket;
140 int fd;
141
142 /* Create a socket */
143 if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { /* Handle the error */
144 RFCNB_errno = RFCNBE_BadSocket;
145 RFCNB_saved_errno = errno;
146 return (RFCNBE_Bad);
147 }
148 bzero((char *) &Socket, sizeof(Socket));
149 memcpy((char *) &Socket.sin_addr, (char *) &Dest_IP, sizeof(Dest_IP));
150
151 Socket.sin_port = htons(port);
152 Socket.sin_family = PF_INET;
153
154 /* Now connect to the destination */
155 if (connect(fd, (struct sockaddr *) &Socket, sizeof(Socket)) < 0) {
156 /* Error */
157 close(fd);
158 RFCNB_errno = RFCNBE_ConnectFailed;
159 RFCNB_saved_errno = errno;
160 return (RFCNBE_Bad);
161 }
162 return fd;
163 }
164
165 /* handle the details of establishing the RFCNB session with remote end */
166 static int
167 RFCNB_Session_Req(struct RFCNB_Con *con,
168 char *Called_Name,
169 char *Calling_Name,
170 BOOL * redirect,
171 struct in_addr *Dest_IP,
172 int *port)
173 {
174 char *sess_pkt;
175
176 /* Response packet should be no more than 9 bytes, make 16 jic */
177 char resp[16];
178 int len;
179 struct RFCNB_Pkt *pkt, res_pkt;
180
181 /* We build and send the session request, then read the response */
182 pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Sess_Len);
183 if (pkt == NULL) {
184 return RFCNBE_Bad; /* Leave the error that RFCNB_Alloc_Pkt gives) */
185 }
186 sess_pkt = pkt->data; /* Get pointer to packet proper */
187
188 sess_pkt[RFCNB_Pkt_Type_Offset] = RFCNB_SESSION_REQUEST;
189 RFCNB_Put_Pkt_Len(sess_pkt, RFCNB_Pkt_Sess_Len - RFCNB_Pkt_Hdr_Len);
190 sess_pkt[RFCNB_Pkt_N1Len_Offset] = 32;
191 sess_pkt[RFCNB_Pkt_N2Len_Offset] = 32;
192
193 RFCNB_CvtPad_Name(Called_Name, (sess_pkt + RFCNB_Pkt_Called_Offset));
194 RFCNB_CvtPad_Name(Calling_Name, (sess_pkt + RFCNB_Pkt_Calling_Offset));
195
196 /* Now send the packet */
197 #ifdef RFCNB_DEBUG
198 fprintf(stderr, "Sending packet: ");
199 #endif
200 if ((len = RFCNB_Put_Pkt(con, pkt, RFCNB_Pkt_Sess_Len)) < 0)
201 return RFCNBE_Bad; /* Should be able to write that lot ... */
202 #ifdef RFCNB_DEBUG
203 fprintf(stderr, "Getting packet.\n");
204 #endif
205
206 res_pkt.data = resp;
207 res_pkt.len = sizeof(resp);
208 res_pkt.next = NULL;
209
210 if ((len = RFCNB_Get_Pkt(con, &res_pkt, sizeof(resp))) < 0)
211 return RFCNBE_Bad;
212
213 /* Now analyze the packet ... */
214 switch (RFCNB_Pkt_Type(resp)) {
215 case RFCNB_SESSION_REJ: /* Didnt like us ... too bad */
216 /* Why did we get rejected ? */
217 switch (CVAL(resp, RFCNB_Pkt_Error_Offset)) {
218 case 0x80:
219 RFCNB_errno = RFCNBE_CallRejNLOCN;
220 break;
221 case 0x81:
222 RFCNB_errno = RFCNBE_CallRejNLFCN;
223 break;
224 case 0x82:
225 RFCNB_errno = RFCNBE_CallRejCNNP;
226 break;
227 case 0x83:
228 RFCNB_errno = RFCNBE_CallRejInfRes;
229 break;
230 case 0x8F:
231 RFCNB_errno = RFCNBE_CallRejUnSpec;
232 break;
233 default:
234 RFCNB_errno = RFCNBE_ProtErr;
235 break;
236 }
237 return (RFCNBE_Bad);
238 break;
239
240 case RFCNB_SESSION_ACK: /* Got what we wanted ... */
241 return (0);
242 break;
243
244 case RFCNB_SESSION_RETARGET: /* Go elsewhere */
245 *redirect = TRUE; /* Copy port and ip addr */
246 memcpy(Dest_IP, (resp + RFCNB_Pkt_IP_Offset),
247 sizeof(struct in_addr));
248 *port = SVAL(resp, RFCNB_Pkt_Port_Offset);
249 return 0;
250 break;
251 default: /* A protocol error */
252 RFCNB_errno = RFCNBE_ProtErr;
253 return (RFCNBE_Bad);
254 break;
255 }
256 }