]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/basic_auth/MSNT/session.c
1 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
6 * Copyright (C) Richard Sharpe 1996
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 int RFCNB_saved_errno
= 0;
30 #include "std-includes.h"
31 #include <netinet/tcp.h>
32 #include "rfcnb-priv.h"
33 #include "rfcnb-util.h"
41 int RFCNB_Stats
[RFCNB_MAX_STATS
];
44 void (*Prot_Print_Routine
) () = NULL
; /* Pointer to print routine */
47 /* Set up a session with a remote name. We are passed Called_Name as a
48 * string which we convert to a NetBIOS name, ie space terminated, up to
49 * 16 characters only if we need to. If Called_Address is not empty, then
50 * we use it to connect to the remote end, but put in Called_Name ... Called
51 * Address can be a DNS based name, or a TCP/IP address ...
55 RFCNB_Call(char *Called_Name
, char *Calling_Name
, char *Called_Address
,
58 struct RFCNB_Con
*con
;
59 struct in_addr Dest_IP
;
62 struct redirect_addr
*redir_addr
;
63 char *Service_Address
;
65 /* Now, we really should look up the port in /etc/services ... */
68 port
= RFCNB_Default_Port
;
70 /* Create a connection structure first */
72 if ((con
= (struct RFCNB_Con
*) malloc(sizeof(struct RFCNB_Con
))) == NULL
) { /* Error in size */
74 RFCNB_errno
= RFCNBE_NoSpace
;
75 RFCNB_saved_errno
= errno
;
79 con
->fd
= -0; /* no descriptor yet */
80 con
->rfc_errno
= 0; /* no error yet */
81 con
->timeout
= 0; /* no timeout */
83 con
->redirect_list
= NULL
; /* Fix bug still in version 0.50 */
85 /* Resolve that name into an IP address */
87 Service_Address
= Called_Name
;
88 if (strcmp(Called_Address
, "") != 0) { /* If the Called Address = "" */
89 Service_Address
= Called_Address
;
91 if ((errno
= RFCNB_Name_To_IP(Service_Address
, &Dest_IP
)) < 0) { /* Error */
93 /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
98 /* Now connect to the remote end */
100 redirect
= TRUE
; /* Fudge this one so we go once through */
102 while (redirect
) { /* Connect and get session info etc */
104 redirect
= FALSE
; /* Assume all OK */
106 /* Build the redirect info. First one is first addr called */
107 /* And tack it onto the list of addresses we called */
109 if ((redir_addr
= (struct redirect_addr
*) malloc(sizeof(struct redirect_addr
))) == NULL
) { /* Could not get space */
111 RFCNB_errno
= RFCNBE_NoSpace
;
112 RFCNB_saved_errno
= errno
;
117 memcpy((char *) &(redir_addr
->ip_addr
), (char *) &Dest_IP
, sizeof(Dest_IP
));
118 redir_addr
->port
= port
;
119 redir_addr
->next
= NULL
;
121 if (con
->redirect_list
== NULL
) { /* Stick on head */
123 con
->redirect_list
= con
->last_addr
= redir_addr
;
127 con
->last_addr
->next
= redir_addr
;
128 con
->last_addr
= redir_addr
;
132 /* Now, make that connection */
134 if ((Client
= RFCNB_IP_Connect(Dest_IP
, port
)) < 0) { /* Error */
136 /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
143 /* Now send and handle the RFCNB session request */
144 /* If we get a redirect, we will comeback with redirect true
145 * and a new IP address in DEST_IP */
147 if ((errno
= RFCNB_Session_Req(con
,
150 &redirect
, &Dest_IP
, &port
)) < 0) {
152 /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
153 RFCNB_Close(con
->fd
); /* Close it */
160 /* We have to close the connection, and then try again */
164 RFCNB_Close(con
->fd
); /* Close it */
173 /* We send a packet to the other end ... for the moment, we treat the
174 * data as a series of pointers to blocks of data ... we should check the
178 RFCNB_Send(struct RFCNB_Con
*Con_Handle
, struct RFCNB_Pkt
*udata
, int Length
)
180 struct RFCNB_Pkt
*pkt
;
184 /* Plug in the header and send the data */
186 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
190 RFCNB_errno
= RFCNBE_NoSpace
;
191 RFCNB_saved_errno
= errno
;
195 pkt
->next
= udata
; /* The user data we want to send */
199 /* Following crap is for portability across multiple UNIX machines */
201 *(hdr
+ RFCNB_Pkt_Type_Offset
) = RFCNB_SESSION_MESSAGE
;
202 RFCNB_Put_Pkt_Len(hdr
, Length
);
206 fprintf(stderr
, "Sending packet: ");
210 if ((len
= RFCNB_Put_Pkt(Con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
212 /* No need to change RFCNB_errno as it was done by put_pkt ... */
214 return (RFCNBE_Bad
); /* Should be able to write that lot ... */
217 /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
227 /* We pick up a message from the internet ... We have to worry about
228 * non-message packets ... */
231 RFCNB_Recv(struct RFCNB_Con
*con_Handle
, struct RFCNB_Pkt
*Data
, int Length
)
233 struct RFCNB_Pkt
*pkt
;
236 if (con_Handle
== NULL
) {
238 RFCNB_errno
= RFCNBE_BadHandle
;
239 RFCNB_saved_errno
= errno
;
243 /* Now get a packet from below. We allocate a header first */
245 /* Plug in the header and send the data */
247 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
251 RFCNB_errno
= RFCNBE_NoSpace
;
252 RFCNB_saved_errno
= errno
;
256 pkt
->next
= Data
; /* Plug in the data portion */
258 if ((ret_len
= RFCNB_Get_Pkt(con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
261 fprintf(stderr
, "Bad packet return in RFCNB_Recv... \n");
267 /* We should check that we go a message and not a keep alive */
277 /* We just disconnect from the other end, as there is nothing in the RFCNB */
278 /* protocol that specifies any exchange as far as I can see */
281 RFCNB_Hangup(struct RFCNB_Con
*con_Handle
)
284 if (con_Handle
!= NULL
) {
285 RFCNB_Close(con_Handle
->fd
); /* Could this fail? */
293 /* Pick up the last error response as a string, hmmm, this routine should */
294 /* have been different ... */
297 RFCNB_Get_Error(char *buffer
, int buf_len
)
300 if (RFCNB_saved_errno
<= 0) {
301 sprintf(buffer
, "%s", RFCNB_Error_Strings
[RFCNB_errno
]);
303 sprintf(buffer
, "%s\n\terrno:%s", RFCNB_Error_Strings
[RFCNB_errno
],
304 strerror(RFCNB_saved_errno
));
309 /* Pick up the last error response and returns as a code */
312 RFCNB_Get_Last_Error(void)
315 return (RFCNB_errno
);
319 /* Pick up saved errno as well */
322 RFCNB_Get_Last_Errno(void)
325 return (RFCNB_saved_errno
);
329 /* Pick up the last error response and return in string ... */
332 RFCNB_Get_Error_Msg(int code
, char *msg_buf
, int len
)
335 strncpy(msg_buf
, RFCNB_Error_Strings
[abs(code
)], len
);
339 /* Register a higher level protocol print routine */
343 RFCNB_Register_Print_Routine(void (*fn
) ())
346 Prot_Print_Routine
= fn
;