]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/session.c
2 * Copyright (C) 1996-2014 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 * Session 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.
36 int RFCNB_saved_errno
= 0;
39 #include "rfcnb/std-includes.h"
40 #include <netinet/tcp.h>
41 #include "rfcnb/rfcnb-io.h"
42 #include "rfcnb/rfcnb-priv.h"
43 #include "rfcnb/rfcnb-util.h"
44 #include "rfcnb/rfcnb.h"
50 int RFCNB_Stats
[RFCNB_MAX_STATS
];
52 RFCNB_Prot_Print_Routine
*Prot_Print_Routine
= NULL
; /* Pointer to protocol print routine */
54 /* Set up a session with a remote name. We are passed Called_Name as a
55 * string which we convert to a NetBIOS name, ie space terminated, up to
56 * 16 characters only if we need to. If Called_Address is not empty, then
57 * we use it to connect to the remote end, but put in Called_Name ... Called
58 * Address can be a DNS based name, or a TCP/IP address ...
62 RFCNB_Call(char *Called_Name
, char *Calling_Name
, char *Called_Address
, int port
)
64 struct RFCNB_Con
*con
;
65 struct in_addr Dest_IP
;
68 struct redirect_addr
*redir_addr
;
69 char *Service_Address
;
71 /* Now, we really should look up the port in /etc/services ... */
74 port
= RFCNB_Default_Port
;
76 /* Create a connection structure first */
78 if ((con
= (struct RFCNB_Con
*) malloc(sizeof(struct RFCNB_Con
))) == NULL
) { /* Error in size */
80 RFCNB_errno
= RFCNBE_NoSpace
;
81 RFCNB_saved_errno
= errno
;
85 con
->fd
= -0; /* no descriptor yet */
86 con
->errn
= 0; /* no error yet */
87 con
->timeout
= 0; /* no timeout */
89 con
->redirect_list
= con
->last_addr
= NULL
;
91 /* Resolve that name into an IP address */
93 Service_Address
= Called_Name
;
94 if (strlen(Called_Address
) != 0) { /* If the Called Address = "" */
95 Service_Address
= Called_Address
;
97 if ((errno
= RFCNB_Name_To_IP(Service_Address
, &Dest_IP
)) < 0) { /* Error */
99 /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
104 /* Now connect to the remote end */
106 redirect
= TRUE
; /* Fudge this one so we go once through */
108 while (redirect
) { /* Connect and get session info etc */
110 redirect
= FALSE
; /* Assume all OK */
112 /* Build the redirect info. First one is first addr called */
113 /* And tack it onto the list of addresses we called */
115 if ((redir_addr
= (struct redirect_addr
*) malloc(sizeof(struct redirect_addr
))) == NULL
) { /* Could not get space */
117 RFCNB_errno
= RFCNBE_NoSpace
;
118 RFCNB_saved_errno
= errno
;
123 memcpy((char *) &(redir_addr
->ip_addr
), (char *) &Dest_IP
, sizeof(Dest_IP
));
124 redir_addr
->port
= port
;
125 redir_addr
->next
= NULL
;
127 if (con
->redirect_list
== NULL
) { /* Stick on head */
129 con
->redirect_list
= con
->last_addr
= redir_addr
;
133 con
->last_addr
->next
= redir_addr
;
134 con
->last_addr
= redir_addr
;
138 /* Now, make that connection */
140 if ((Client
= RFCNB_IP_Connect(Dest_IP
, port
)) < 0) { /* Error */
142 /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
149 /* Now send and handle the RFCNB session request */
150 /* If we get a redirect, we will comeback with redirect true
151 * and a new IP address in DEST_IP */
153 if ((errno
= RFCNB_Session_Req(con
,
156 &redirect
, &Dest_IP
, &port
)) < 0) {
158 /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
160 RFCNB_Close(con
->fd
); /* Close it */
167 /* We have to close the connection, and then try again */
171 RFCNB_Close(con
->fd
); /* Close it */
179 /* We send a packet to the other end ... for the moment, we treat the
180 * data as a series of pointers to blocks of data ... we should check the
183 RFCNB_Send(struct RFCNB_Con
*Con_Handle
, struct RFCNB_Pkt
*udata
, int Length
)
185 struct RFCNB_Pkt
*pkt
;
189 /* Plug in the header and send the data */
191 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
195 RFCNB_errno
= RFCNBE_NoSpace
;
196 RFCNB_saved_errno
= errno
;
200 pkt
->next
= udata
; /* The user data we want to send */
204 /* Following crap is for portability across multiple UNIX machines */
206 *(hdr
+ RFCNB_Pkt_Type_Offset
) = RFCNB_SESSION_MESSAGE
;
207 RFCNB_Put_Pkt_Len(hdr
, Length
);
211 fprintf(stderr
, "Sending packet: ");
215 if ((len
= RFCNB_Put_Pkt(Con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
217 /* No need to change RFCNB_errno as it was done by put_pkt ... */
220 return (RFCNBE_Bad
); /* Should be able to write that lot ... */
223 /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
232 /* We pick up a message from the internet ... We have to worry about
233 * non-message packets ... */
235 RFCNB_Recv(void *con_Handle
, struct RFCNB_Pkt
*Data
, int Length
)
237 struct RFCNB_Pkt
*pkt
;
238 // struct RFCNB_Hdr *hdr;
241 if (con_Handle
== NULL
) {
243 RFCNB_errno
= RFCNBE_BadHandle
;
244 RFCNB_saved_errno
= errno
;
248 /* Now get a packet from below. We allocate a header first */
250 /* Plug in the header and send the data */
252 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
256 RFCNB_errno
= RFCNBE_NoSpace
;
257 RFCNB_saved_errno
= errno
;
261 pkt
->next
= Data
; /* Plug in the data portion */
263 if ((ret_len
= RFCNB_Get_Pkt(con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
266 fprintf(stderr
, "Bad packet return in RFCNB_Recv... \n");
272 /* We should check that we go a message and not a keep alive */
281 /* We just disconnect from the other end, as there is nothing in the RFCNB */
282 /* protocol that specifies any exchange as far as I can see */
284 RFCNB_Hangup(struct RFCNB_Con
*con_Handle
)
287 if (con_Handle
!= NULL
) {
288 RFCNB_Close(con_Handle
->fd
); /* Could this fail? */
294 /* Set TCP_NODELAY on the socket */
296 RFCNB_Set_Sock_NoDelay(struct RFCNB_Con
*con_Handle
, BOOL yn
)
299 return (setsockopt(con_Handle
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
300 (char *) &yn
, sizeof(yn
)));
304 /* Listen for a connection on a port???, when */
305 /* the connection comes in, we return with the connection */
313 /* Pick up the last error response as a string, hmmm, this routine should */
314 /* have been different ... */
316 RFCNB_Get_Error(char *buffer
, int buf_len
)
319 if (RFCNB_saved_errno
<= 0) {
320 snprintf(buffer
, (buf_len
- 1), "%s", RFCNB_Error_Strings
[RFCNB_errno
]);
322 snprintf(buffer
, (buf_len
- 1), "%s\n\terrno:%s", RFCNB_Error_Strings
[RFCNB_errno
],
323 strerror(RFCNB_saved_errno
));
327 /* Pick up the last error response and returns as a code */
329 RFCNB_Get_Last_Error()
331 return (RFCNB_errno
);