]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/session.c
3 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
8 * Copyright (C) Richard Sharpe 1996
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 int RFCNB_saved_errno
= 0;
32 #include "rfcnb/std-includes.h"
33 #include <netinet/tcp.h>
34 #include "rfcnb/rfcnb.h"
35 #include "rfcnb/rfcnb-priv.h"
36 #include "rfcnb/rfcnb-io.h"
37 #include "rfcnb/rfcnb-util.h"
43 int RFCNB_Stats
[RFCNB_MAX_STATS
];
45 RFCNB_Prot_Print_Routine
*Prot_Print_Routine
= NULL
; /* Pointer to protocol 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
, int port
)
57 struct RFCNB_Con
*con
;
58 struct in_addr Dest_IP
;
61 struct redirect_addr
*redir_addr
;
62 char *Service_Address
;
64 /* Now, we really should look up the port in /etc/services ... */
67 port
= RFCNB_Default_Port
;
69 /* Create a connection structure first */
71 if ((con
= (struct RFCNB_Con
*) malloc(sizeof(struct RFCNB_Con
))) == NULL
) { /* Error in size */
73 RFCNB_errno
= RFCNBE_NoSpace
;
74 RFCNB_saved_errno
= errno
;
78 con
->fd
= -0; /* no descriptor yet */
79 con
->errn
= 0; /* no error yet */
80 con
->timeout
= 0; /* no timeout */
83 /* Resolve that name into an IP address */
85 Service_Address
= Called_Name
;
86 if (strcmp(Called_Address
, "") != 0) { /* If the Called Address = "" */
87 Service_Address
= Called_Address
;
89 if ((errno
= RFCNB_Name_To_IP(Service_Address
, &Dest_IP
)) < 0) { /* Error */
91 /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
96 /* Now connect to the remote end */
98 redirect
= TRUE
; /* Fudge this one so we go once through */
100 while (redirect
) { /* Connect and get session info etc */
102 redirect
= FALSE
; /* Assume all OK */
104 /* Build the redirect info. First one is first addr called */
105 /* And tack it onto the list of addresses we called */
107 if ((redir_addr
= (struct redirect_addr
*) malloc(sizeof(struct redirect_addr
))) == NULL
) { /* Could not get space */
109 RFCNB_errno
= RFCNBE_NoSpace
;
110 RFCNB_saved_errno
= errno
;
115 memcpy((char *) &(redir_addr
->ip_addr
), (char *) &Dest_IP
, sizeof(Dest_IP
));
116 redir_addr
->port
= port
;
117 redir_addr
->next
= NULL
;
119 if (con
->redirect_list
== NULL
) { /* Stick on head */
121 con
->redirect_list
= con
->last_addr
= redir_addr
;
125 con
->last_addr
->next
= redir_addr
;
126 con
->last_addr
= redir_addr
;
130 /* Now, make that connection */
132 if ((Client
= RFCNB_IP_Connect(Dest_IP
, port
)) < 0) { /* Error */
134 /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
141 /* Now send and handle the RFCNB session request */
142 /* If we get a redirect, we will comeback with redirect true
143 * and a new IP address in DEST_IP */
145 if ((errno
= RFCNB_Session_Req(con
,
148 &redirect
, &Dest_IP
, &port
)) < 0) {
150 /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
152 RFCNB_Close(con
->fd
); /* Close it */
159 /* We have to close the connection, and then try again */
163 RFCNB_Close(con
->fd
); /* Close it */
171 /* We send a packet to the other end ... for the moment, we treat the
172 * data as a series of pointers to blocks of data ... we should check the
175 RFCNB_Send(struct RFCNB_Con
*Con_Handle
, struct RFCNB_Pkt
*udata
, int Length
)
177 struct RFCNB_Pkt
*pkt
;
181 /* Plug in the header and send the data */
183 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
187 RFCNB_errno
= RFCNBE_NoSpace
;
188 RFCNB_saved_errno
= errno
;
192 pkt
->next
= udata
; /* The user data we want to send */
196 /* Following crap is for portability across multiple UNIX machines */
198 *(hdr
+ RFCNB_Pkt_Type_Offset
) = RFCNB_SESSION_MESSAGE
;
199 RFCNB_Put_Pkt_Len(hdr
, Length
);
203 fprintf(stderr
, "Sending packet: ");
207 if ((len
= RFCNB_Put_Pkt(Con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
209 /* No need to change RFCNB_errno as it was done by put_pkt ... */
211 return (RFCNBE_Bad
); /* Should be able to write that lot ... */
214 /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
223 /* We pick up a message from the internet ... We have to worry about
224 * non-message packets ... */
226 RFCNB_Recv(void *con_Handle
, struct RFCNB_Pkt
*Data
, int Length
)
228 struct RFCNB_Pkt
*pkt
;
229 // struct RFCNB_Hdr *hdr;
232 if (con_Handle
== NULL
) {
234 RFCNB_errno
= RFCNBE_BadHandle
;
235 RFCNB_saved_errno
= errno
;
239 /* Now get a packet from below. We allocate a header first */
241 /* Plug in the header and send the data */
243 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
247 RFCNB_errno
= RFCNBE_NoSpace
;
248 RFCNB_saved_errno
= errno
;
252 pkt
->next
= Data
; /* Plug in the data portion */
254 if ((ret_len
= RFCNB_Get_Pkt(con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
257 fprintf(stderr
, "Bad packet return in RFCNB_Recv... \n");
263 /* We should check that we go a message and not a keep alive */
272 /* We just disconnect from the other end, as there is nothing in the RFCNB */
273 /* protocol that specifies any exchange as far as I can see */
275 RFCNB_Hangup(struct RFCNB_Con
*con_Handle
)
278 if (con_Handle
!= NULL
) {
279 RFCNB_Close(con_Handle
->fd
); /* Could this fail? */
285 /* Set TCP_NODELAY on the socket */
287 RFCNB_Set_Sock_NoDelay(struct RFCNB_Con
*con_Handle
, BOOL yn
)
290 return (setsockopt(con_Handle
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
291 (char *) &yn
, sizeof(yn
)));
295 /* Listen for a connection on a port???, when */
296 /* the connection comes in, we return with the connection */
304 /* Pick up the last error response as a string, hmmm, this routine should */
305 /* have been different ... */
307 RFCNB_Get_Error(char *buffer
, int buf_len
)
310 if (RFCNB_saved_errno
<= 0) {
311 snprintf(buffer
, (buf_len
- 1), "%s", RFCNB_Error_Strings
[RFCNB_errno
]);
313 snprintf(buffer
, (buf_len
- 1), "%s\n\terrno:%s", RFCNB_Error_Strings
[RFCNB_errno
],
314 strerror(RFCNB_saved_errno
));
318 /* Pick up the last error response and returns as a code */
320 RFCNB_Get_Last_Error()
322 return (RFCNB_errno
);