protosw.h revision 160342
11541Srgrimes/*- 21541Srgrimes * Copyright (c) 1982, 1986, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 4. Neither the name of the University nor the names of its contributors 141541Srgrimes * may be used to endorse or promote products derived from this software 151541Srgrimes * without specific prior written permission. 161541Srgrimes * 171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271541Srgrimes * SUCH DAMAGE. 281541Srgrimes * 291541Srgrimes * @(#)protosw.h 8.1 (Berkeley) 6/2/93 3050477Speter * $FreeBSD: head/sys/sys/protosw.h 160342 2006-07-14 09:44:28Z rwatson $ 311541Srgrimes */ 321541Srgrimes 332165Spaul#ifndef _SYS_PROTOSW_H_ 342165Spaul#define _SYS_PROTOSW_H_ 352165Spaul 3623888Swollman/* Forward declare these structures referenced from prototypes below. */ 3712453Sbdestruct mbuf; 3883366Sjulianstruct thread; 3912453Sbdestruct sockaddr; 4012453Sbdestruct socket; 4138482Swollmanstruct sockopt; 4212453Sbde 4355205Speter/*#ifdef _KERNEL*/ 441541Srgrimes/* 451541Srgrimes * Protocol switch table. 461541Srgrimes * 471541Srgrimes * Each protocol has a handle initializing one of these structures, 481541Srgrimes * which is used for protocol-protocol and system-protocol communication. 491541Srgrimes * 501541Srgrimes * A protocol is called through the pr_init entry before any other. 511541Srgrimes * Thereafter it is called every 200ms through the pr_fasttimo entry and 521541Srgrimes * every 500ms through the pr_slowtimo for timer based actions. 531541Srgrimes * The system will call the pr_drain entry if it is low on space and 541541Srgrimes * this should throw away any non-critical data. 551541Srgrimes * 561541Srgrimes * Protocols pass data between themselves as chains of mbufs using 571541Srgrimes * the pr_input and pr_output hooks. Pr_input passes data up (towards 5838482Swollman * the users) and pr_output passes it down (towards the interfaces); control 591541Srgrimes * information passes up and down on pr_ctlinput and pr_ctloutput. 601541Srgrimes * The protocol is responsible for the space occupied by any the 611541Srgrimes * arguments to these entries and must dispose it. 621541Srgrimes * 6338482Swollman * In retrospect, it would be a lot nicer to use an interface 6438482Swollman * similar to the vnode VOP interface. 651541Srgrimes */ 6681501Sjulian/* USE THESE FOR YOUR PROTOTYPES ! */ 6781501Sjuliantypedef void pr_input_t (struct mbuf *, int); 6882824Sjuliantypedef int pr_input6_t (struct mbuf **, int*, int); /* XXX FIX THIS */ 6981501Sjuliantypedef void pr_in_input_t (struct mbuf *, int, int); /* XXX FIX THIS */ 7081501Sjuliantypedef int pr_output_t (struct mbuf *, struct socket *); 7182824Sjuliantypedef int pr_in_output_t (struct mbuf *, struct socket *, struct sockaddr *); 7281501Sjuliantypedef void pr_ctlinput_t (int, struct sockaddr *, void *); 7381501Sjuliantypedef int pr_ctloutput_t (struct socket *, struct sockopt *); 7481501Sjuliantypedef void pr_init_t (void); 7581501Sjuliantypedef void pr_fasttimo_t (void); 7681501Sjuliantypedef void pr_slowtimo_t (void); 7781501Sjuliantypedef void pr_drain_t (void); 7881501Sjulian 7982824Sjuliantypedef int pr_usrreq_t(struct socket *, int, struct mbuf *, 8083366Sjulian struct mbuf *, struct mbuf *, struct thread *); 8181501Sjulian 821541Srgrimesstruct protosw { 831541Srgrimes short pr_type; /* socket type used for */ 841541Srgrimes struct domain *pr_domain; /* domain protocol a member of */ 851541Srgrimes short pr_protocol; /* protocol number */ 861541Srgrimes short pr_flags; /* see below */ 871541Srgrimes/* protocol-protocol hooks */ 8881501Sjulian pr_input_t *pr_input; /* input to protocol (from below) */ 8981501Sjulian pr_output_t *pr_output; /* output to protocol (from above) */ 9081501Sjulian pr_ctlinput_t *pr_ctlinput; /* control input (from below) */ 9181501Sjulian pr_ctloutput_t *pr_ctloutput; /* control output (from above) */ 921541Srgrimes/* user-protocol hook */ 9382824Sjulian pr_usrreq_t *pr_ousrreq; 941541Srgrimes/* utility hooks */ 9581501Sjulian pr_init_t *pr_init; 9681501Sjulian pr_fasttimo_t *pr_fasttimo; /* fast timeout (200ms) */ 9781501Sjulian pr_slowtimo_t *pr_slowtimo; /* slow timeout (500ms) */ 9881501Sjulian pr_drain_t *pr_drain; /* flush any excess space possible */ 9981501Sjulian 10017047Swollman struct pr_usrreqs *pr_usrreqs; /* supersedes pr_usrreq() */ 1011541Srgrimes}; 10228270Swollman/*#endif*/ 1031541Srgrimes 1041541Srgrimes#define PR_SLOWHZ 2 /* 2 slow timeouts per second */ 1051541Srgrimes#define PR_FASTHZ 5 /* 5 fast timeouts per second */ 1061541Srgrimes 1071541Srgrimes/* 108136692Sandre * This number should be defined again within each protocol family to avoid 109136692Sandre * confusion. 110136692Sandre */ 111136692Sandre#define PROTO_SPACER 32767 /* spacer for loadable protocols */ 112136692Sandre 113136692Sandre/* 1141541Srgrimes * Values for pr_flags. 1151541Srgrimes * PR_ADDR requires PR_ATOMIC; 1161541Srgrimes * PR_ADDR and PR_CONNREQUIRED are mutually exclusive. 1176223Swollman * PR_IMPLOPCL means that the protocol allows sendto without prior connect, 1186223Swollman * and the protocol understands the MSG_EOF flag. The first property is 1196223Swollman * is only relevant if PR_CONNREQUIRED is set (otherwise sendto is allowed 1206223Swollman * anyhow). 1211541Srgrimes */ 1221541Srgrimes#define PR_ATOMIC 0x01 /* exchange atomic messages only */ 1231541Srgrimes#define PR_ADDR 0x02 /* addresses given with messages */ 1241541Srgrimes#define PR_CONNREQUIRED 0x04 /* connection required by protocol */ 1251541Srgrimes#define PR_WANTRCVD 0x08 /* want PRU_RCVD calls */ 1261541Srgrimes#define PR_RIGHTS 0x10 /* passes capabilities */ 1276223Swollman#define PR_IMPLOPCL 0x20 /* implied open/close */ 12878064Sume#define PR_LASTHDR 0x40 /* enforce ipsec policy; last header */ 1291541Srgrimes 1301541Srgrimes/* 131159374Srwatson * In earlier BSD network stacks, a single pr_usrreq() function pointer was 132159374Srwatson * invoked with an operation number indicating what operation was desired. 133159374Srwatson * We now provide individual function pointers which protocols can implement, 134159374Srwatson * which offers a number of benefits (such as type checking for arguments). 135159374Srwatson * These older constants are still present in order to support TCP debugging. 136159374Srwatson * 137159374Srwatson * The arguments to usrreq were: 1381541Srgrimes * (*protosw[].pr_usrreq)(up, req, m, nam, opt); 1391541Srgrimes * where up is a (struct socket *), req is one of these requests, 140108533Sschweikh * m is an optional mbuf chain containing a message, 1411541Srgrimes * nam is an optional mbuf chain containing an address, 1421541Srgrimes * and opt is a pointer to a socketopt structure or nil. 1431541Srgrimes * The protocol is responsible for disposal of the mbuf chain m, 1441541Srgrimes * the caller is responsible for any space held by nam and opt. 1451541Srgrimes * A non-zero return from usrreq gives an 1461541Srgrimes * UNIX error number which should be passed to higher level software. 1471541Srgrimes */ 1481541Srgrimes#define PRU_ATTACH 0 /* attach protocol to up */ 1491541Srgrimes#define PRU_DETACH 1 /* detach protocol from up */ 1501541Srgrimes#define PRU_BIND 2 /* bind socket to address */ 1511541Srgrimes#define PRU_LISTEN 3 /* listen for connection */ 1521541Srgrimes#define PRU_CONNECT 4 /* establish connection to peer */ 1531541Srgrimes#define PRU_ACCEPT 5 /* accept connection from peer */ 1541541Srgrimes#define PRU_DISCONNECT 6 /* disconnect from peer */ 1551541Srgrimes#define PRU_SHUTDOWN 7 /* won't send any more data */ 1561541Srgrimes#define PRU_RCVD 8 /* have taken data; more room now */ 1571541Srgrimes#define PRU_SEND 9 /* send this data */ 1581541Srgrimes#define PRU_ABORT 10 /* abort (fast DISCONNECT, DETATCH) */ 1591541Srgrimes#define PRU_CONTROL 11 /* control operations on protocol */ 1601541Srgrimes#define PRU_SENSE 12 /* return status into m */ 1611541Srgrimes#define PRU_RCVOOB 13 /* retrieve out of band data */ 1621541Srgrimes#define PRU_SENDOOB 14 /* send out of band data */ 1631541Srgrimes#define PRU_SOCKADDR 15 /* fetch socket's address */ 1641541Srgrimes#define PRU_PEERADDR 16 /* fetch peer's address */ 1651541Srgrimes#define PRU_CONNECT2 17 /* connect two sockets */ 1661541Srgrimes/* begin for protocols internal use */ 1671541Srgrimes#define PRU_FASTTIMO 18 /* 200ms timeout */ 1681541Srgrimes#define PRU_SLOWTIMO 19 /* 500ms timeout */ 1691541Srgrimes#define PRU_PROTORCV 20 /* receive from below */ 1701541Srgrimes#define PRU_PROTOSEND 21 /* send to below */ 17117047Swollman/* end for protocol's internal use */ 1726223Swollman#define PRU_SEND_EOF 22 /* send and close */ 173160342Srwatson#define PRU_SOSETLABEL 23 /* MAC label change */ 174160342Srwatson#define PRU_CLOSE 24 /* socket close */ 175160342Srwatson#define PRU_NREQ 24 1761541Srgrimes 1771541Srgrimes#ifdef PRUREQUESTS 178101975Salfredconst char *prurequests[] = { 1791541Srgrimes "ATTACH", "DETACH", "BIND", "LISTEN", 1801541Srgrimes "CONNECT", "ACCEPT", "DISCONNECT", "SHUTDOWN", 1811541Srgrimes "RCVD", "SEND", "ABORT", "CONTROL", 1821541Srgrimes "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR", 1831541Srgrimes "PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO", 184160342Srwatson "PROTORCV", "PROTOSEND", "SEND_EOF", "SOSETLABEL", 185160342Srwatson "CLOSE", 1861541Srgrimes}; 1871541Srgrimes#endif 1881541Srgrimes 18955205Speter#ifdef _KERNEL /* users shouldn't see this decl */ 19017047Swollman 19132995Sbdestruct ifnet; 19232995Sbdestruct stat; 19332995Sbdestruct ucred; 19432995Sbdestruct uio; 19532995Sbde 1961541Srgrimes/* 197159374Srwatson * If the ordering here looks odd, that's because it's alphabetical. These 198159374Srwatson * should eventually be merged back into struct protosw. 199137386Sphk * 200137386Sphk * Some fields initialized to defaults if they are NULL. 201137386Sphk * See uipc_domain.c:net_init_domain() 20217047Swollman */ 20317047Swollmanstruct pr_usrreqs { 204137386Sphk double __Break_the_struct_layout_for_now; 205157366Srwatson void (*pru_abort)(struct socket *so); 20692719Salfred int (*pru_accept)(struct socket *so, struct sockaddr **nam); 20792719Salfred int (*pru_attach)(struct socket *so, int proto, struct thread *td); 20892719Salfred int (*pru_bind)(struct socket *so, struct sockaddr *nam, 20993008Sbde struct thread *td); 21092719Salfred int (*pru_connect)(struct socket *so, struct sockaddr *nam, 21193008Sbde struct thread *td); 21292719Salfred int (*pru_connect2)(struct socket *so1, struct socket *so2); 21392719Salfred int (*pru_control)(struct socket *so, u_long cmd, caddr_t data, 21493008Sbde struct ifnet *ifp, struct thread *td); 215157370Srwatson void (*pru_detach)(struct socket *so); 21692719Salfred int (*pru_disconnect)(struct socket *so); 217151888Srwatson int (*pru_listen)(struct socket *so, int backlog, 218151888Srwatson struct thread *td); 21992719Salfred int (*pru_peeraddr)(struct socket *so, struct sockaddr **nam); 22092719Salfred int (*pru_rcvd)(struct socket *so, int flags); 22192719Salfred int (*pru_rcvoob)(struct socket *so, struct mbuf *m, int flags); 22292719Salfred int (*pru_send)(struct socket *so, int flags, struct mbuf *m, 22393008Sbde struct sockaddr *addr, struct mbuf *control, 22493008Sbde struct thread *td); 22517047Swollman#define PRUS_OOB 0x1 22617047Swollman#define PRUS_EOF 0x2 22742902Sfenner#define PRUS_MORETOCOME 0x4 22892719Salfred int (*pru_sense)(struct socket *so, struct stat *sb); 22992719Salfred int (*pru_shutdown)(struct socket *so); 23092719Salfred int (*pru_sockaddr)(struct socket *so, struct sockaddr **nam); 23123888Swollman 23223888Swollman /* 233159374Srwatson * These four added later, so they are out of order. They are used 23423888Swollman * for shortcutting (fast path input/output) in some protocols. 23523888Swollman * XXX - that's a lie, they are not implemented yet 23625201Swollman * Rather than calling sosend() etc. directly, calls are made 23725201Swollman * through these entry points. For protocols which still use 23825201Swollman * the generic code, these just point to those routines. 23923888Swollman */ 24092719Salfred int (*pru_sosend)(struct socket *so, struct sockaddr *addr, 24193008Sbde struct uio *uio, struct mbuf *top, struct mbuf *control, 24293008Sbde int flags, struct thread *td); 24393008Sbde int (*pru_soreceive)(struct socket *so, struct sockaddr **paddr, 24493008Sbde struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, 24593008Sbde int *flagsp); 24692719Salfred int (*pru_sopoll)(struct socket *so, int events, 24793008Sbde struct ucred *cred, struct thread *td); 248122875Srwatson void (*pru_sosetlabel)(struct socket *so); 249160342Srwatson void (*pru_close)(struct socket *so); 25017047Swollman}; 25117047Swollman 252136692Sandre/* 253148965Sobrien * All nonvoid pru_*() functions below return EOPNOTSUPP. 254136692Sandre */ 25592719Salfredint pru_accept_notsupp(struct socket *so, struct sockaddr **nam); 256136692Sandreint pru_attach_notsupp(struct socket *so, int proto, struct thread *td); 257136692Sandreint pru_bind_notsupp(struct socket *so, struct sockaddr *nam, 258136692Sandre struct thread *td); 25992719Salfredint pru_connect_notsupp(struct socket *so, struct sockaddr *nam, 26093008Sbde struct thread *td); 26192719Salfredint pru_connect2_notsupp(struct socket *so1, struct socket *so2); 26292719Salfredint pru_control_notsupp(struct socket *so, u_long cmd, caddr_t data, 26393008Sbde struct ifnet *ifp, struct thread *td); 264136692Sandreint pru_disconnect_notsupp(struct socket *so); 265151888Srwatsonint pru_listen_notsupp(struct socket *so, int backlog, struct thread *td); 266136692Sandreint pru_peeraddr_notsupp(struct socket *so, struct sockaddr **nam); 26792719Salfredint pru_rcvd_notsupp(struct socket *so, int flags); 26892719Salfredint pru_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags); 269136692Sandreint pru_send_notsupp(struct socket *so, int flags, struct mbuf *m, 270136692Sandre struct sockaddr *addr, struct mbuf *control, struct thread *td); 27192719Salfredint pru_sense_null(struct socket *so, struct stat *sb); 272136692Sandreint pru_shutdown_notsupp(struct socket *so); 273136692Sandreint pru_sockaddr_notsupp(struct socket *so, struct sockaddr **nam); 274136692Sandreint pru_sosend_notsupp(struct socket *so, struct sockaddr *addr, 275136692Sandre struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, 276136692Sandre struct thread *td); 277136692Sandreint pru_soreceive_notsupp(struct socket *so, struct sockaddr **paddr, 278136692Sandre struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, 279136692Sandre int *flagsp); 280136692Sandreint pru_sopoll_notsupp(struct socket *so, int events, struct ucred *cred, 281136692Sandre struct thread *td); 28217096Swollman 28355205Speter#endif /* _KERNEL */ 28417047Swollman 28517047Swollman/* 2861541Srgrimes * The arguments to the ctlinput routine are 2871541Srgrimes * (*protosw[].pr_ctlinput)(cmd, sa, arg); 2881541Srgrimes * where cmd is one of the commands below, sa is a pointer to a sockaddr, 28912881Sbde * and arg is a `void *' argument used within a protocol family. 2901541Srgrimes */ 2911541Srgrimes#define PRC_IFDOWN 0 /* interface transition */ 2921541Srgrimes#define PRC_ROUTEDEAD 1 /* select new route if possible ??? */ 29322614Swollman#define PRC_IFUP 2 /* interface has come back up */ 2941541Srgrimes#define PRC_QUENCH2 3 /* DEC congestion bit says slow down */ 2951541Srgrimes#define PRC_QUENCH 4 /* some one said to slow down */ 2961541Srgrimes#define PRC_MSGSIZE 5 /* message size forced drop */ 2971541Srgrimes#define PRC_HOSTDEAD 6 /* host appears to be down */ 2981541Srgrimes#define PRC_HOSTUNREACH 7 /* deprecated (use PRC_UNREACH_HOST) */ 2991541Srgrimes#define PRC_UNREACH_NET 8 /* no route to network */ 3001541Srgrimes#define PRC_UNREACH_HOST 9 /* no route to host */ 3011541Srgrimes#define PRC_UNREACH_PROTOCOL 10 /* dst says bad protocol */ 3021541Srgrimes#define PRC_UNREACH_PORT 11 /* bad port # */ 3031541Srgrimes/* was PRC_UNREACH_NEEDFRAG 12 (use PRC_MSGSIZE) */ 3041541Srgrimes#define PRC_UNREACH_SRCFAIL 13 /* source route failed */ 3051541Srgrimes#define PRC_REDIRECT_NET 14 /* net routing redirect */ 3061541Srgrimes#define PRC_REDIRECT_HOST 15 /* host routing redirect */ 3071541Srgrimes#define PRC_REDIRECT_TOSNET 16 /* redirect for type of service & net */ 3081541Srgrimes#define PRC_REDIRECT_TOSHOST 17 /* redirect for tos & host */ 3091541Srgrimes#define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */ 3101541Srgrimes#define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */ 3111541Srgrimes#define PRC_PARAMPROB 20 /* header incorrect */ 31272638Sphk#define PRC_UNREACH_ADMIN_PROHIB 21 /* packet administrativly prohibited */ 3131541Srgrimes 31472638Sphk#define PRC_NCMDS 22 3151541Srgrimes 3161541Srgrimes#define PRC_IS_REDIRECT(cmd) \ 3171541Srgrimes ((cmd) >= PRC_REDIRECT_NET && (cmd) <= PRC_REDIRECT_TOSHOST) 3181541Srgrimes 3191541Srgrimes#ifdef PRCREQUESTS 3201541Srgrimeschar *prcrequests[] = { 32122614Swollman "IFDOWN", "ROUTEDEAD", "IFUP", "DEC-BIT-QUENCH2", 3221541Srgrimes "QUENCH", "MSGSIZE", "HOSTDEAD", "#7", 3231541Srgrimes "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH", 3241541Srgrimes "#12", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT", 3251541Srgrimes "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS", 32672638Sphk "PARAMPROB", "ADMIN-UNREACH" 3271541Srgrimes}; 3281541Srgrimes#endif 3291541Srgrimes 3301541Srgrimes/* 3311541Srgrimes * The arguments to ctloutput are: 33225201Swollman * (*protosw[].pr_ctloutput)(req, so, level, optname, optval, p); 3331541Srgrimes * req is one of the actions listed below, so is a (struct socket *), 3341541Srgrimes * level is an indication of which protocol layer the option is intended. 3351541Srgrimes * optname is a protocol dependent socket option request, 3361541Srgrimes * optval is a pointer to a mbuf-chain pointer, for value-return results. 3371541Srgrimes * The protocol is responsible for disposal of the mbuf chain *optval 3381541Srgrimes * if supplied, 3391541Srgrimes * the caller is responsible for any space held by *optval, when returned. 3401541Srgrimes * A non-zero return from usrreq gives an 3411541Srgrimes * UNIX error number which should be passed to higher level software. 3421541Srgrimes */ 3431541Srgrimes#define PRCO_GETOPT 0 3441541Srgrimes#define PRCO_SETOPT 1 3451541Srgrimes 3461541Srgrimes#define PRCO_NCMDS 2 3471541Srgrimes 3481541Srgrimes#ifdef PRCOREQUESTS 3491541Srgrimeschar *prcorequests[] = { 3501541Srgrimes "GETOPT", "SETOPT", 3511541Srgrimes}; 3521541Srgrimes#endif 3531541Srgrimes 35455205Speter#ifdef _KERNEL 35592719Salfredvoid pfctlinput(int, struct sockaddr *); 35692719Salfredvoid pfctlinput2(int, struct sockaddr *, void *); 35792719Salfredstruct protosw *pffindproto(int family, int protocol, int type); 35892719Salfredstruct protosw *pffindtype(int family, int type); 359136692Sandreint pf_proto_register(int family, struct protosw *npr); 360136692Sandreint pf_proto_unregister(int family, int protocol, int type); 3611541Srgrimes#endif 3622165Spaul 3632165Spaul#endif 364