"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: session.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
2
3
4 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
5 *
6 * Version 1.0 Session Routines ...
7 *
8 * Copyright (C) Richard Sharpe 1996
9 *
10 */
11
12 /*
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. This program is distributed in the hope
17 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
18 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details. You
20 * should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 675 Mass Ave, Cambridge, MA 02139, USA. */
23
24 #include <malloc.h>
25 #include <string.h>
26
27 static int RFCNB_errno = 0;
28 static int RFCNB_saved_errno = 0;
29 #define RFCNB_ERRNO
30
31 #include "std-includes.h"
32 #include <netinet/tcp.h>
33 #include "rfcnb-priv.h"
34 #include "rfcnb-util.h"
35
36 /* Set up a session with a remote name. We are passed Called_Name as a
37 * string which we convert to a NetBIOS name, ie space terminated, up to
38 * 16 characters only if we need to. If Called_Address is not empty, then
39 * we use it to connect to the remote end, but put in Called_Name ...
40 * Called Address can be a DNS based name, or a TCP/IP address ... */
41 static void *
42 RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address,
43 int port)
44 {
45 struct RFCNB_Con *con;
46 struct in_addr Dest_IP;
47 int Client;
48 BOOL redirect;
49 struct redirect_addr *redir_addr;
50 char *Service_Address;
51
52 /* Now, we really should look up the port in /etc/services ... */
53 if (port == 0)
54 port = RFCNB_Default_Port;
55
56 /* Create a connection structure first */
57 if ((con = (struct RFCNB_Con *) malloc(
58 sizeof(struct RFCNB_Con))) == NULL) {
59 /* Error in size */
60 RFCNB_errno = RFCNBE_NoSpace;
61 RFCNB_saved_errno = errno;
62 return NULL;
63 }
64 con->fd = -0; /* no descriptor yet */
65 con->rfc_errno = 0; /* no error yet */
66 con->timeout = 0; /* no timeout */
67 con->redirects = 0;
68 con->redirect_list = NULL; /* Fix bug still in version 0.50 */
69
70 /* Resolve that name into an IP address */
71 Service_Address = Called_Name;
72 if (strcmp(Called_Address, "") != 0)
73 Service_Address = Called_Address;
74 if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) {
75 /* Error */
76 /* No need to modify RFCNB_errno as it was done by
77 * RFCNB_Name_To_IP */
78 return NULL;
79 }
80 /* Now connect to the remote end */
81 redirect = TRUE; /* Fudge this one so we go once through */
82 while (redirect) { /* Connect and get session info etc */
83 redirect = FALSE; /* Assume all OK */
84 /* Build the redirect info. First one is first addr called */
85 /* And tack it onto the list of addresses we called */
86 if ((redir_addr = (struct redirect_addr *) malloc(
87 sizeof(struct redirect_addr))) == NULL) {
88 /* Could not get space */
89 RFCNB_errno = RFCNBE_NoSpace;
90 RFCNB_saved_errno = errno;
91 return (NULL);
92 }
93 memcpy((char *) &(redir_addr->ip_addr),
94 (char *) &Dest_IP, sizeof(Dest_IP));
95 redir_addr->port = port;
96 redir_addr->next = NULL;
97
98 if (con->redirect_list == NULL) { /* Stick on head */
99 con->redirect_list = con->last_addr = redir_addr;
100 } else {
101 con->last_addr->next = redir_addr;
102 con->last_addr = redir_addr;
103 }
104
105 /* Now, make that connection */
106 if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */
107 /* No need to modify RFCNB_errno as it was done by
108 * RFCNB_IP_Connect */
109 return NULL;
110 }
111 con->fd = Client;
112
113 /* Now send and handle the RFCNB session request */
114 /* If we get a redirect, we will comeback with redirect true and
115 * a new IP address in DEST_IP */
116 if ((errno = RFCNB_Session_Req(con,
117 Called_Name,
118 Calling_Name,
119 &redirect, &Dest_IP, &port)) < 0) {
120 /* No need to modify RFCNB_errno as it was done by
121 * RFCNB_Session.. */
122 return NULL;
123 }
124 if (redirect) {
125 /* We have to close the connection, and then try again */
126 (con->redirects)++;
127 RFCNB_Close(con->fd); /* Close it */
128 }
129 }
130 return con;
131 }
132
133 /* We send a packet to the other end ... for the moment, we treat the
134 * data as a series of pointers to blocks of data ... we should check the
135 * length ... */
136 static int
137 RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
138 {
139 struct RFCNB_Pkt *pkt;
140 char *hdr;
141 int len;
142
143 /* Plug in the header and send the data */
144 pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
145 if (pkt == NULL) {
146 RFCNB_errno = RFCNBE_NoSpace;
147 RFCNB_saved_errno = errno;
148 return (RFCNBE_Bad);
149 }
150 pkt->next = udata; /* The user data we want to send */
151 hdr = pkt->data;
152
153 /* Following crap is for portability across multiple UNIX machines */
154 *(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
155 RFCNB_Put_Pkt_Len(hdr, Length);
156
157 #ifdef RFCNB_DEBUG
158 fprintf(stderr, "Sending packet: ");
159 #endif
160
161 if ((len = RFCNB_Put_Pkt(Con_Handle, pkt,
162 Length + RFCNB_Pkt_Hdr_Len)) < 0) {
163 /* No need to change RFCNB_errno as it was done by put_pkt ... */
164 return RFCNBE_Bad; /* Should be able to write that lot ... */
165 }
166 /* Now we have sent that lot, let's get rid of the RFCNB Header
167 * and return */
168 pkt->next = NULL;
169
170 RFCNB_Free_Pkt(pkt);
171 return len;
172 }
173
174 /* We pick up a message from the internet ... We have to worry about
175 * non-message packets ... */
176 static int
177 RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
178 {
179 struct RFCNB_Pkt *pkt;
180 int ret_len;
181
182 if (con_Handle == NULL) {
183 RFCNB_errno = RFCNBE_BadHandle;
184 RFCNB_saved_errno = errno;
185 return (RFCNBE_Bad);
186 }
187 /* Now get a packet from below. We allocate a header first */
188 /* Plug in the header and send the data */
189 pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
190
191 if (pkt == NULL) {
192 RFCNB_errno = RFCNBE_NoSpace;
193 RFCNB_saved_errno = errno;
194 return (RFCNBE_Bad);
195 }
196 pkt->next = Data; /* Plug in the data portion */
197
198 if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt,
199 Length + RFCNB_Pkt_Hdr_Len)) < 0) {
200 #ifdef RFCNB_DEBUG
201 fprintf(stderr, "Bad packet return in RFCNB_Recv... \n");
202 #endif
203 return RFCNBE_Bad;
204 }
205 /* We should check that we go a message and not a keep alive */
206 pkt->next = NULL;
207 RFCNB_Free_Pkt(pkt);
208 return ret_len;
209 }
210
211 /* We just disconnect from the other end, as there is nothing in the
212 * RFCNB protocol that specifies any exchange as far as I can see*/
213 static int
214 RFCNB_Hangup(struct RFCNB_Con *con_Handle)
215 {
216 if (con_Handle != NULL) {
217 RFCNB_Close(con_Handle->fd); /* Could this fail? */
218 free(con_Handle);
219 }
220 return 0;
221 }