| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668 | diff -Nur linux-2.6.30.1.orig/include/net/xfrmudp.h linux-2.6.30.1/include/net/xfrmudp.h--- linux-2.6.30.1.orig/include/net/xfrmudp.h	1970-01-01 01:00:00.000000000 +0100+++ linux-2.6.30.1/include/net/xfrmudp.h	2009-07-24 22:00:56.771280384 +0200@@ -0,0 +1,10 @@+/*+ * pointer to function for type that xfrm4_input wants, to permit+ * decoupling of XFRM from udp.c+ */+#define HAVE_XFRM4_UDP_REGISTER++typedef int (*xfrm4_rcv_encap_t)(struct sk_buff *skb, __u16 encap_type);+extern int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func+				      , xfrm4_rcv_encap_t *oldfunc);+extern int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func);diff -Nur linux-2.6.30.1.orig/net/ipv4/Kconfig linux-2.6.30.1/net/ipv4/Kconfig--- linux-2.6.30.1.orig/net/ipv4/Kconfig	2009-07-03 01:52:38.000000000 +0200+++ linux-2.6.30.1/net/ipv4/Kconfig	2009-07-24 22:00:56.751278392 +0200@@ -379,6 +379,12 @@ 	tristate 	default n +config IPSEC_NAT_TRAVERSAL+	bool "IPSEC NAT-Traversal (KLIPS compatible)"+	depends on INET+	---help---+          Includes support for RFC3947/RFC3948 NAT-Traversal of ESP over UDP.+ config INET_XFRM_MODE_TRANSPORT 	tristate "IP: IPsec transport mode" 	default ydiff -Nur linux-2.6.30.1.orig/net/ipv4/Kconfig.orig linux-2.6.30.1/net/ipv4/Kconfig.orig--- linux-2.6.30.1.orig/net/ipv4/Kconfig.orig	1970-01-01 01:00:00.000000000 +0100+++ linux-2.6.30.1/net/ipv4/Kconfig.orig	2009-07-03 01:52:38.000000000 +0200@@ -0,0 +1,638 @@+#+# IP configuration+#+config IP_MULTICAST+	bool "IP: multicasting"+	help+	  This is code for addressing several networked computers at once,+	  enlarging your kernel by about 2 KB. You need multicasting if you+	  intend to participate in the MBONE, a high bandwidth network on top+	  of the Internet which carries audio and video broadcasts. More+	  information about the MBONE is on the WWW at+	  <http://www.savetz.com/mbone/>. Information about the multicast+	  capabilities of the various network cards is contained in+	  <file:Documentation/networking/multicast.txt>. For most people, it's+	  safe to say N.++config IP_ADVANCED_ROUTER+	bool "IP: advanced router"+	---help---+	  If you intend to run your Linux box mostly as a router, i.e. as a+	  computer that forwards and redistributes network packets, say Y; you+	  will then be presented with several options that allow more precise+	  control about the routing process.++	  The answer to this question won't directly affect the kernel:+	  answering N will just cause the configurator to skip all the+	  questions about advanced routing.++	  Note that your box can only act as a router if you enable IP+	  forwarding in your kernel; you can do that by saying Y to "/proc+	  file system support" and "Sysctl support" below and executing the+	  line++	  echo "1" > /proc/sys/net/ipv4/ip_forward++	  at boot time after the /proc file system has been mounted.++	  If you turn on IP forwarding, you should consider the rp_filter, which+	  automatically rejects incoming packets if the routing table entry+	  for their source address doesn't match the network interface they're+	  arriving on. This has security advantages because it prevents the+	  so-called IP spoofing, however it can pose problems if you use+	  asymmetric routing (packets from you to a host take a different path+	  than packets from that host to you) or if you operate a non-routing+	  host which has several IP addresses on different interfaces. To turn+	  rp_filter on use:++	  echo 1 > /proc/sys/net/ipv4/conf/<device>/rp_filter+	   and+	  echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter++	  Note that some distributions enable it in startup scripts.+	  For details about rp_filter strict and loose mode read+	  <file:Documentation/networking/ip-sysctl.txt>.++	  If unsure, say N here.++choice+	prompt "Choose IP: FIB lookup algorithm (choose FIB_HASH if unsure)"+	depends on IP_ADVANCED_ROUTER+	default ASK_IP_FIB_HASH++config ASK_IP_FIB_HASH+	bool "FIB_HASH"+	---help---+	  Current FIB is very proven and good enough for most users.++config IP_FIB_TRIE+	bool "FIB_TRIE"+	---help---+	  Use new experimental LC-trie as FIB lookup algorithm.+	  This improves lookup performance if you have a large+	  number of routes.++	  LC-trie is a longest matching prefix lookup algorithm which+	  performs better than FIB_HASH for large routing tables.+	  But, it consumes more memory and is more complex.++	  LC-trie is described in:++	  IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson+	  IEEE Journal on Selected Areas in Communications, 17(6):1083-1092,+	  June 1999++	  An experimental study of compression methods for dynamic tries+	  Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.+	  http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/++endchoice++config IP_FIB_HASH+	def_bool ASK_IP_FIB_HASH || !IP_ADVANCED_ROUTER++config IP_FIB_TRIE_STATS+	bool "FIB TRIE statistics"+	depends on IP_FIB_TRIE+	---help---+	  Keep track of statistics on structure of FIB TRIE table.+	  Useful for testing and measuring TRIE performance.++config IP_MULTIPLE_TABLES+	bool "IP: policy routing"+	depends on IP_ADVANCED_ROUTER+	select FIB_RULES+	---help---+	  Normally, a router decides what to do with a received packet based+	  solely on the packet's final destination address. If you say Y here,+	  the Linux router will also be able to take the packet's source+	  address into account. Furthermore, the TOS (Type-Of-Service) field+	  of the packet can be used for routing decisions as well.++	  If you are interested in this, please see the preliminary+	  documentation at <http://www.compendium.com.ar/policy-routing.txt>+	  and <ftp://post.tepkom.ru/pub/vol2/Linux/docs/advanced-routing.tex>.+	  You will need supporting software from+	  <ftp://ftp.tux.org/pub/net/ip-routing/>.++	  If unsure, say N.++config IP_ROUTE_MULTIPATH+	bool "IP: equal cost multipath"+	depends on IP_ADVANCED_ROUTER+	help+	  Normally, the routing tables specify a single action to be taken in+	  a deterministic manner for a given packet. If you say Y here+	  however, it becomes possible to attach several actions to a packet+	  pattern, in effect specifying several alternative paths to travel+	  for those packets. The router considers all these paths to be of+	  equal "cost" and chooses one of them in a non-deterministic fashion+	  if a matching packet arrives.++config IP_ROUTE_VERBOSE+	bool "IP: verbose route monitoring"+	depends on IP_ADVANCED_ROUTER+	help+	  If you say Y here, which is recommended, then the kernel will print+	  verbose messages regarding the routing, for example warnings about+	  received packets which look strange and could be evidence of an+	  attack or a misconfigured system somewhere. The information is+	  handled by the klogd daemon which is responsible for kernel messages+	  ("man klogd").++config IP_PNP+	bool "IP: kernel level autoconfiguration"+	help+	  This enables automatic configuration of IP addresses of devices and+	  of the routing table during kernel boot, based on either information+	  supplied on the kernel command line or by BOOTP or RARP protocols.+	  You need to say Y only for diskless machines requiring network+	  access to boot (in which case you want to say Y to "Root file system+	  on NFS" as well), because all other machines configure the network+	  in their startup scripts.++config IP_PNP_DHCP+	bool "IP: DHCP support"+	depends on IP_PNP+	---help---+	  If you want your Linux box to mount its whole root file system (the+	  one containing the directory /) from some other computer over the+	  net via NFS and you want the IP address of your computer to be+	  discovered automatically at boot time using the DHCP protocol (a+	  special protocol designed for doing this job), say Y here. In case+	  the boot ROM of your network card was designed for booting Linux and+	  does DHCP itself, providing all necessary information on the kernel+	  command line, you can say N here.++	  If unsure, say Y. Note that if you want to use DHCP, a DHCP server+	  must be operating on your network.  Read+	  <file:Documentation/filesystems/nfsroot.txt> for details.++config IP_PNP_BOOTP+	bool "IP: BOOTP support"+	depends on IP_PNP+	---help---+	  If you want your Linux box to mount its whole root file system (the+	  one containing the directory /) from some other computer over the+	  net via NFS and you want the IP address of your computer to be+	  discovered automatically at boot time using the BOOTP protocol (a+	  special protocol designed for doing this job), say Y here. In case+	  the boot ROM of your network card was designed for booting Linux and+	  does BOOTP itself, providing all necessary information on the kernel+	  command line, you can say N here. If unsure, say Y. Note that if you+	  want to use BOOTP, a BOOTP server must be operating on your network.+	  Read <file:Documentation/filesystems/nfsroot.txt> for details.++config IP_PNP_RARP+	bool "IP: RARP support"+	depends on IP_PNP+	help+	  If you want your Linux box to mount its whole root file system (the+	  one containing the directory /) from some other computer over the+	  net via NFS and you want the IP address of your computer to be+	  discovered automatically at boot time using the RARP protocol (an+	  older protocol which is being obsoleted by BOOTP and DHCP), say Y+	  here. Note that if you want to use RARP, a RARP server must be+	  operating on your network. Read+	  <file:Documentation/filesystems/nfsroot.txt> for details.++# not yet ready..+#   bool '    IP: ARP support' CONFIG_IP_PNP_ARP+config NET_IPIP+	tristate "IP: tunneling"+	select INET_TUNNEL+	---help---+	  Tunneling means encapsulating data of one protocol type within+	  another protocol and sending it over a channel that understands the+	  encapsulating protocol. This particular tunneling driver implements+	  encapsulation of IP within IP, which sounds kind of pointless, but+	  can be useful if you want to make your (or some other) machine+	  appear on a different network than it physically is, or to use+	  mobile-IP facilities (allowing laptops to seamlessly move between+	  networks without changing their IP addresses).++	  Saying Y to this option will produce two modules ( = code which can+	  be inserted in and removed from the running kernel whenever you+	  want). Most people won't need this and can say N.++config NET_IPGRE+	tristate "IP: GRE tunnels over IP"+	help+	  Tunneling means encapsulating data of one protocol type within+	  another protocol and sending it over a channel that understands the+	  encapsulating protocol. This particular tunneling driver implements+	  GRE (Generic Routing Encapsulation) and at this time allows+	  encapsulating of IPv4 or IPv6 over existing IPv4 infrastructure.+	  This driver is useful if the other endpoint is a Cisco router: Cisco+	  likes GRE much better than the other Linux tunneling driver ("IP+	  tunneling" above). In addition, GRE allows multicast redistribution+	  through the tunnel.++config NET_IPGRE_BROADCAST+	bool "IP: broadcast GRE over IP"+	depends on IP_MULTICAST && NET_IPGRE+	help+	  One application of GRE/IP is to construct a broadcast WAN (Wide Area+	  Network), which looks like a normal Ethernet LAN (Local Area+	  Network), but can be distributed all over the Internet. If you want+	  to do that, say Y here and to "IP multicast routing" below.++config IP_MROUTE+	bool "IP: multicast routing"+	depends on IP_MULTICAST+	help+	  This is used if you want your machine to act as a router for IP+	  packets that have several destination addresses. It is needed on the+	  MBONE, a high bandwidth network on top of the Internet which carries+	  audio and video broadcasts. In order to do that, you would most+	  likely run the program mrouted. Information about the multicast+	  capabilities of the various network cards is contained in+	  <file:Documentation/networking/multicast.txt>. If you haven't heard+	  about it, you don't need it.++config IP_PIMSM_V1+	bool "IP: PIM-SM version 1 support"+	depends on IP_MROUTE+	help+	  Kernel side support for Sparse Mode PIM (Protocol Independent+	  Multicast) version 1. This multicast routing protocol is used widely+	  because Cisco supports it. You need special software to use it+	  (pimd-v1). Please see <http://netweb.usc.edu/pim/> for more+	  information about PIM.++	  Say Y if you want to use PIM-SM v1. Note that you can say N here if+	  you just want to use Dense Mode PIM.++config IP_PIMSM_V2+	bool "IP: PIM-SM version 2 support"+	depends on IP_MROUTE+	help+	  Kernel side support for Sparse Mode PIM version 2. In order to use+	  this, you need an experimental routing daemon supporting it (pimd or+	  gated-5). This routing protocol is not used widely, so say N unless+	  you want to play with it.++config ARPD+	bool "IP: ARP daemon support (EXPERIMENTAL)"+	depends on EXPERIMENTAL+	---help---+	  Normally, the kernel maintains an internal cache which maps IP+	  addresses to hardware addresses on the local network, so that+	  Ethernet/Token Ring/ etc. frames are sent to the proper address on+	  the physical networking layer. For small networks having a few+	  hundred directly connected hosts or less, keeping this address+	  resolution (ARP) cache inside the kernel works well. However,+	  maintaining an internal ARP cache does not work well for very large+	  switched networks, and will use a lot of kernel memory if TCP/IP+	  connections are made to many machines on the network.++	  If you say Y here, the kernel's internal ARP cache will never grow+	  to more than 256 entries (the oldest entries are expired in a LIFO+	  manner) and communication will be attempted with the user space ARP+	  daemon arpd. Arpd then answers the address resolution request either+	  from its own cache or by asking the net.++	  This code is experimental and also obsolete. If you want to use it,+	  you need to find a version of the daemon arpd on the net somewhere,+	  and you should also say Y to "Kernel/User network link driver",+	  below. If unsure, say N.++config SYN_COOKIES+	bool "IP: TCP syncookie support (disabled per default)"+	---help---+	  Normal TCP/IP networking is open to an attack known as "SYN+	  flooding". This denial-of-service attack prevents legitimate remote+	  users from being able to connect to your computer during an ongoing+	  attack and requires very little work from the attacker, who can+	  operate from anywhere on the Internet.++	  SYN cookies provide protection against this type of attack. If you+	  say Y here, the TCP/IP stack will use a cryptographic challenge+	  protocol known as "SYN cookies" to enable legitimate users to+	  continue to connect, even when your machine is under attack. There+	  is no need for the legitimate users to change their TCP/IP software;+	  SYN cookies work transparently to them. For technical information+	  about SYN cookies, check out <http://cr.yp.to/syncookies.html>.++	  If you are SYN flooded, the source address reported by the kernel is+	  likely to have been forged by the attacker; it is only reported as+	  an aid in tracing the packets to their actual source and should not+	  be taken as absolute truth.++	  SYN cookies may prevent correct error reporting on clients when the+	  server is really overloaded. If this happens frequently better turn+	  them off.++	  If you say Y here, note that SYN cookies aren't enabled by default;+	  you can enable them by saying Y to "/proc file system support" and+	  "Sysctl support" below and executing the command++	  echo 1 >/proc/sys/net/ipv4/tcp_syncookies++	  at boot time after the /proc file system has been mounted.++	  If unsure, say N.++config INET_AH+	tristate "IP: AH transformation"+	select XFRM+	select CRYPTO+	select CRYPTO_HMAC+	select CRYPTO_MD5+	select CRYPTO_SHA1+	---help---+	  Support for IPsec AH.++	  If unsure, say Y.++config INET_ESP+	tristate "IP: ESP transformation"+	select XFRM+	select CRYPTO+	select CRYPTO_AUTHENC+	select CRYPTO_HMAC+	select CRYPTO_MD5+	select CRYPTO_CBC+	select CRYPTO_SHA1+	select CRYPTO_DES+	---help---+	  Support for IPsec ESP.++	  If unsure, say Y.++config INET_IPCOMP+	tristate "IP: IPComp transformation"+	select INET_XFRM_TUNNEL+	select XFRM_IPCOMP+	---help---+	  Support for IP Payload Compression Protocol (IPComp) (RFC3173),+	  typically needed for IPsec.++	  If unsure, say Y.++config INET_XFRM_TUNNEL+	tristate+	select INET_TUNNEL+	default n++config INET_TUNNEL+	tristate+	default n++config INET_XFRM_MODE_TRANSPORT+	tristate "IP: IPsec transport mode"+	default y+	select XFRM+	---help---+	  Support for IPsec transport mode.++	  If unsure, say Y.++config INET_XFRM_MODE_TUNNEL+	tristate "IP: IPsec tunnel mode"+	default y+	select XFRM+	---help---+	  Support for IPsec tunnel mode.++	  If unsure, say Y.++config INET_XFRM_MODE_BEET+	tristate "IP: IPsec BEET mode"+	default y+	select XFRM+	---help---+	  Support for IPsec BEET mode.++	  If unsure, say Y.++config INET_LRO+	bool "Large Receive Offload (ipv4/tcp)"+	default y+	---help---+	  Support for Large Receive Offload (ipv4/tcp).++	  If unsure, say Y.++config INET_DIAG+	tristate "INET: socket monitoring interface"+	default y+	---help---+	  Support for INET (TCP, DCCP, etc) socket monitoring interface used by+	  native Linux tools such as ss. ss is included in iproute2, currently+	  downloadable at <http://linux-net.osdl.org/index.php/Iproute2>.++	  If unsure, say Y.++config INET_TCP_DIAG+	depends on INET_DIAG+	def_tristate INET_DIAG++menuconfig TCP_CONG_ADVANCED+	bool "TCP: advanced congestion control"+	---help---+	  Support for selection of various TCP congestion control+	  modules.++	  Nearly all users can safely say no here, and a safe default+	  selection will be made (CUBIC with new Reno as a fallback).++	  If unsure, say N.++if TCP_CONG_ADVANCED++config TCP_CONG_BIC+	tristate "Binary Increase Congestion (BIC) control"+	default m+	---help---+	BIC-TCP is a sender-side only change that ensures a linear RTT+	fairness under large windows while offering both scalability and+	bounded TCP-friendliness. The protocol combines two schemes+	called additive increase and binary search increase. When the+	congestion window is large, additive increase with a large+	increment ensures linear RTT fairness as well as good+	scalability. Under small congestion windows, binary search+	increase provides TCP friendliness.+	See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/++config TCP_CONG_CUBIC+	tristate "CUBIC TCP"+	default y+	---help---+	This is version 2.0 of BIC-TCP which uses a cubic growth function+	among other techniques.+	See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf++config TCP_CONG_WESTWOOD+	tristate "TCP Westwood+"+	default m+	---help---+	TCP Westwood+ is a sender-side only modification of the TCP Reno+	protocol stack that optimizes the performance of TCP congestion+	control. It is based on end-to-end bandwidth estimation to set+	congestion window and slow start threshold after a congestion+	episode. Using this estimation, TCP Westwood+ adaptively sets a+	slow start threshold and a congestion window which takes into+	account the bandwidth used  at the time congestion is experienced.+	TCP Westwood+ significantly increases fairness wrt TCP Reno in+	wired networks and throughput over wireless links.++config TCP_CONG_HTCP+        tristate "H-TCP"+        default m+	---help---+	H-TCP is a send-side only modifications of the TCP Reno+	protocol stack that optimizes the performance of TCP+	congestion control for high speed network links. It uses a+	modeswitch to change the alpha and beta parameters of TCP Reno+	based on network conditions and in a way so as to be fair with+	other Reno and H-TCP flows.++config TCP_CONG_HSTCP+	tristate "High Speed TCP"+	depends on EXPERIMENTAL+	default n+	---help---+	Sally Floyd's High Speed TCP (RFC 3649) congestion control.+	A modification to TCP's congestion control mechanism for use+	with large congestion windows. A table indicates how much to+	increase the congestion window by when an ACK is received.+ 	For more detail	see http://www.icir.org/floyd/hstcp.html++config TCP_CONG_HYBLA+	tristate "TCP-Hybla congestion control algorithm"+	depends on EXPERIMENTAL+	default n+	---help---+	TCP-Hybla is a sender-side only change that eliminates penalization of+	long-RTT, large-bandwidth connections, like when satellite legs are+	involved, especially when sharing a common bottleneck with normal+	terrestrial connections.++config TCP_CONG_VEGAS+	tristate "TCP Vegas"+	depends on EXPERIMENTAL+	default n+	---help---+	TCP Vegas is a sender-side only change to TCP that anticipates+	the onset of congestion by estimating the bandwidth. TCP Vegas+	adjusts the sending rate by modifying the congestion+	window. TCP Vegas should provide less packet loss, but it is+	not as aggressive as TCP Reno.++config TCP_CONG_SCALABLE+	tristate "Scalable TCP"+	depends on EXPERIMENTAL+	default n+	---help---+	Scalable TCP is a sender-side only change to TCP which uses a+	MIMD congestion control algorithm which has some nice scaling+	properties, though is known to have fairness issues.+	See http://www.deneholme.net/tom/scalable/++config TCP_CONG_LP+	tristate "TCP Low Priority"+	depends on EXPERIMENTAL+	default n+	---help---+	TCP Low Priority (TCP-LP), a distributed algorithm whose goal is+	to utilize only the excess network bandwidth as compared to the+	``fair share`` of bandwidth as targeted by TCP.+	See http://www-ece.rice.edu/networks/TCP-LP/++config TCP_CONG_VENO+	tristate "TCP Veno"+	depends on EXPERIMENTAL+	default n+	---help---+	TCP Veno is a sender-side only enhancement of TCP to obtain better+	throughput over wireless networks. TCP Veno makes use of state+	distinguishing to circumvent the difficult judgment of the packet loss+	type. TCP Veno cuts down less congestion window in response to random+	loss packets.+	See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf++config TCP_CONG_YEAH+	tristate "YeAH TCP"+	depends on EXPERIMENTAL+	select TCP_CONG_VEGAS+	default n+	---help---+	YeAH-TCP is a sender-side high-speed enabled TCP congestion control+	algorithm, which uses a mixed loss/delay approach to compute the+	congestion window. It's design goals target high efficiency,+	internal, RTT and Reno fairness, resilience to link loss while+	keeping network elements load as low as possible.++	For further details look here:+	  http://wil.cs.caltech.edu/pfldnet2007/paper/YeAH_TCP.pdf++config TCP_CONG_ILLINOIS+	tristate "TCP Illinois"+	depends on EXPERIMENTAL+	default n+	---help---+	TCP-Illinois is a sender-side modification of TCP Reno for+	high speed long delay links. It uses round-trip-time to+	adjust the alpha and beta parameters to achieve a higher average+	throughput and maintain fairness.++	For further details see:+	  http://www.ews.uiuc.edu/~shaoliu/tcpillinois/index.html++choice+	prompt "Default TCP congestion control"+	default DEFAULT_CUBIC+	help+	  Select the TCP congestion control that will be used by default+	  for all connections.++	config DEFAULT_BIC+		bool "Bic" if TCP_CONG_BIC=y++	config DEFAULT_CUBIC+		bool "Cubic" if TCP_CONG_CUBIC=y++	config DEFAULT_HTCP+		bool "Htcp" if TCP_CONG_HTCP=y++	config DEFAULT_VEGAS+		bool "Vegas" if TCP_CONG_VEGAS=y++	config DEFAULT_WESTWOOD+		bool "Westwood" if TCP_CONG_WESTWOOD=y++	config DEFAULT_RENO+		bool "Reno"++endchoice++endif++config TCP_CONG_CUBIC+	tristate+	depends on !TCP_CONG_ADVANCED+	default y++config DEFAULT_TCP_CONG+	string+	default "bic" if DEFAULT_BIC+	default "cubic" if DEFAULT_CUBIC+	default "htcp" if DEFAULT_HTCP+	default "vegas" if DEFAULT_VEGAS+	default "westwood" if DEFAULT_WESTWOOD+	default "reno" if DEFAULT_RENO+	default "cubic"++config TCP_MD5SIG+	bool "TCP: MD5 Signature Option support (RFC2385) (EXPERIMENTAL)"+	depends on EXPERIMENTAL+	select CRYPTO+	select CRYPTO_MD5+	---help---+	  RFC2385 specifies a method of giving MD5 protection to TCP sessions.+	  Its main (only?) use is to protect BGP sessions between core routers+	  on the Internet.++	  If unsure, say N.+diff -Nur linux-2.6.30.1.orig/net/ipv4/udp.c linux-2.6.30.1/net/ipv4/udp.c--- linux-2.6.30.1.orig/net/ipv4/udp.c	2009-07-03 01:52:38.000000000 +0200+++ linux-2.6.30.1/net/ipv4/udp.c	2009-07-24 22:00:56.755270521 +0200@@ -104,6 +104,7 @@ #include <net/route.h> #include <net/checksum.h> #include <net/xfrm.h>+#include <net/xfrmudp.h> #include "udp_impl.h"  struct udp_table udp_table;@@ -1035,6 +1036,128 @@ 	return -1; } +#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL)++static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = NULL;++/*+ * de-encapsulate and pass to the registered xfrm4_rcv_encap_func function.+ * Most of this code stolen from net/ipv4/xfrm4_input.c+ * which is attributed to YOSHIFUJI Hideaki @USAGI, and+ * Derek Atkins <derek@ihtfp.com>+ */++static int xfrm4_udp_encap_rcv_wrapper(struct sock *sk, struct sk_buff *skb)+{+	struct udp_sock *up = udp_sk(sk);+	struct udphdr *uh;+	struct iphdr *iph;+	int iphlen, len;+	int ret;++	__u8 *udpdata;+	__be32 *udpdata32;+	__u16 encap_type = up->encap_type;++	/* if this is not encapsulated socket, then just return now */+	if (!encap_type && !xfrm4_rcv_encap_func)+		return 1;++	/* If this is a paged skb, make sure we pull up+	 * whatever data we need to look at. */+	len = skb->len - sizeof(struct udphdr);+	if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))+		return 1;++	/* Now we can get the pointers */+	uh = udp_hdr(skb);+	udpdata = (__u8 *)uh + sizeof(struct udphdr);+	udpdata32 = (__be32 *)udpdata;++	switch (encap_type) {+	default:+	case UDP_ENCAP_ESPINUDP:+		/* Check if this is a keepalive packet.  If so, eat it. */+		if (len == 1 && udpdata[0] == 0xff) {+			goto drop;+		} else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {+			/* ESP Packet without Non-ESP header */+			len = sizeof(struct udphdr);+		} else+			/* Must be an IKE packet.. pass it through */+			return 1;+		break;+	case UDP_ENCAP_ESPINUDP_NON_IKE:+		/* Check if this is a keepalive packet.  If so, eat it. */+		if (len == 1 && udpdata[0] == 0xff) {+			goto drop;+		} else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&+			   udpdata32[0] == 0 && udpdata32[1] == 0) {++			/* ESP Packet with Non-IKE marker */+			len = sizeof(struct udphdr) + 2 * sizeof(u32);+		} else+			/* Must be an IKE packet.. pass it through */+			return 1;+		break;+	}++	/* At this point we are sure that this is an ESPinUDP packet,+	 * so we need to remove 'len' bytes from the packet (the UDP+	 * header and optional ESP marker bytes) and then modify the+	 * protocol to ESP, and then call into the transform receiver.+	 */+	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))+		goto drop;++	/* Now we can update and verify the packet length... */+	iph = ip_hdr(skb);+	iphlen = iph->ihl << 2;+	iph->tot_len = htons(ntohs(iph->tot_len) - len);+	if (skb->len < iphlen + len) {+		/* packet is too small!?! */+		goto drop;+	}++	/* pull the data buffer up to the ESP header and set the+	 * transport header to point to ESP.  Keep UDP on the stack+	 * for later.+	 */+	__skb_pull(skb, len);+	skb_reset_transport_header(skb);++	/* modify the protocol (it's ESP!) */+	iph->protocol = IPPROTO_ESP;++	/* process ESP */+	ret = (*xfrm4_rcv_encap_func)(skb, encap_type);+	return ret;++drop:+	kfree_skb(skb);+	return 0;+}++int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func,+		xfrm4_rcv_encap_t *oldfunc)+{+	if (oldfunc != NULL)+		*oldfunc = xfrm4_rcv_encap_func;+	xfrm4_rcv_encap_func = func;+	return 0;+}++int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func)+{+	if (xfrm4_rcv_encap_func != func)+		return -1;++	xfrm4_rcv_encap_func = NULL;+	return 0;+}++#endif /* CONFIG_XFRM_MODULE || CONFIG_IPSEC_NAT_TRAVERSAL */+ /* returns:  *  -1: error  *   0: success@@ -1377,6 +1500,11 @@ 		case 0: 		case UDP_ENCAP_ESPINUDP: 		case UDP_ENCAP_ESPINUDP_NON_IKE:+#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL)+			if (xfrm4_rcv_encap_func)+				up->encap_rcv = xfrm4_udp_encap_rcv_wrapper;+			else+#endif 			up->encap_rcv = xfrm4_udp_encap_rcv; 			/* FALLTHROUGH */ 		case UDP_ENCAP_L2TPINUDP:@@ -1828,3 +1956,9 @@ EXPORT_SYMBOL(udp_proc_register); EXPORT_SYMBOL(udp_proc_unregister); #endif++#if defined(CONFIG_IPSEC_NAT_TRAVERSAL)+EXPORT_SYMBOL(udp4_register_esp_rcvencap);+EXPORT_SYMBOL(udp4_unregister_esp_rcvencap);+#endif+diff -Nur linux-2.6.30.1.orig/net/ipv4/udp.c.orig linux-2.6.30.1/net/ipv4/udp.c.orig--- linux-2.6.30.1.orig/net/ipv4/udp.c.orig	1970-01-01 01:00:00.000000000 +0100+++ linux-2.6.30.1/net/ipv4/udp.c.orig	2009-07-03 01:52:38.000000000 +0200@@ -0,0 +1,1830 @@+/*+ * INET		An implementation of the TCP/IP protocol suite for the LINUX+ *		operating system.  INET is implemented using the  BSD Socket+ *		interface as the means of communication with the user level.+ *+ *		The User Datagram Protocol (UDP).+ *+ * Authors:	Ross Biro+ *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>+ *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>+ *		Alan Cox, <alan@lxorguk.ukuu.org.uk>+ *		Hirokazu Takahashi, <taka@valinux.co.jp>+ *+ * Fixes:+ *		Alan Cox	:	verify_area() calls+ *		Alan Cox	: 	stopped close while in use off icmp+ *					messages. Not a fix but a botch that+ *					for udp at least is 'valid'.+ *		Alan Cox	:	Fixed icmp handling properly+ *		Alan Cox	: 	Correct error for oversized datagrams+ *		Alan Cox	:	Tidied select() semantics.+ *		Alan Cox	:	udp_err() fixed properly, also now+ *					select and read wake correctly on errors+ *		Alan Cox	:	udp_send verify_area moved to avoid mem leak+ *		Alan Cox	:	UDP can count its memory+ *		Alan Cox	:	send to an unknown connection causes+ *					an ECONNREFUSED off the icmp, but+ *					does NOT close.+ *		Alan Cox	:	Switched to new sk_buff handlers. No more backlog!+ *		Alan Cox	:	Using generic datagram code. Even smaller and the PEEK+ *					bug no longer crashes it.+ *		Fred Van Kempen	: 	Net2e support for sk->broadcast.+ *		Alan Cox	:	Uses skb_free_datagram+ *		Alan Cox	:	Added get/set sockopt support.+ *		Alan Cox	:	Broadcasting without option set returns EACCES.+ *		Alan Cox	:	No wakeup calls. Instead we now use the callbacks.+ *		Alan Cox	:	Use ip_tos and ip_ttl+ *		Alan Cox	:	SNMP Mibs+ *		Alan Cox	:	MSG_DONTROUTE, and 0.0.0.0 support.+ *		Matt Dillon	:	UDP length checks.+ *		Alan Cox	:	Smarter af_inet used properly.+ *		Alan Cox	:	Use new kernel side addressing.+ *		Alan Cox	:	Incorrect return on truncated datagram receive.+ *	Arnt Gulbrandsen 	:	New udp_send and stuff+ *		Alan Cox	:	Cache last socket+ *		Alan Cox	:	Route cache+ *		Jon Peatfield	:	Minor efficiency fix to sendto().+ *		Mike Shaver	:	RFC1122 checks.+ *		Alan Cox	:	Nonblocking error fix.+ *	Willy Konynenberg	:	Transparent proxying support.+ *		Mike McLagan	:	Routing by source+ *		David S. Miller	:	New socket lookup architecture.+ *					Last socket cache retained as it+ *					does have a high hit rate.+ *		Olaf Kirch	:	Don't linearise iovec on sendmsg.+ *		Andi Kleen	:	Some cleanups, cache destination entry+ *					for connect.+ *	Vitaly E. Lavrov	:	Transparent proxy revived after year coma.+ *		Melvin Smith	:	Check msg_name not msg_namelen in sendto(),+ *					return ENOTCONN for unconnected sockets (POSIX)+ *		Janos Farkas	:	don't deliver multi/broadcasts to a different+ *					bound-to-device socket+ *	Hirokazu Takahashi	:	HW checksumming for outgoing UDP+ *					datagrams.+ *	Hirokazu Takahashi	:	sendfile() on UDP works now.+ *		Arnaldo C. Melo :	convert /proc/net/udp to seq_file+ *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which+ *	Alexey Kuznetsov:		allow both IPv4 and IPv6 sockets to bind+ *					a single port at the same time.+ *	Derek Atkins <derek@ihtfp.com>: Add Encapulation Support+ *	James Chapman		:	Add L2TP encapsulation type.+ *+ *+ *		This program is free software; you can redistribute it and/or+ *		modify it under the terms of the GNU General Public License+ *		as published by the Free Software Foundation; either version+ *		2 of the License, or (at your option) any later version.+ */++#include <asm/system.h>+#include <asm/uaccess.h>+#include <asm/ioctls.h>+#include <linux/bootmem.h>+#include <linux/highmem.h>+#include <linux/swap.h>+#include <linux/types.h>+#include <linux/fcntl.h>+#include <linux/module.h>+#include <linux/socket.h>+#include <linux/sockios.h>+#include <linux/igmp.h>+#include <linux/in.h>+#include <linux/errno.h>+#include <linux/timer.h>+#include <linux/mm.h>+#include <linux/inet.h>+#include <linux/netdevice.h>+#include <net/tcp_states.h>+#include <linux/skbuff.h>+#include <linux/proc_fs.h>+#include <linux/seq_file.h>+#include <net/net_namespace.h>+#include <net/icmp.h>+#include <net/route.h>+#include <net/checksum.h>+#include <net/xfrm.h>+#include "udp_impl.h"++struct udp_table udp_table;+EXPORT_SYMBOL(udp_table);++int sysctl_udp_mem[3] __read_mostly;+int sysctl_udp_rmem_min __read_mostly;+int sysctl_udp_wmem_min __read_mostly;++EXPORT_SYMBOL(sysctl_udp_mem);+EXPORT_SYMBOL(sysctl_udp_rmem_min);+EXPORT_SYMBOL(sysctl_udp_wmem_min);++atomic_t udp_memory_allocated;+EXPORT_SYMBOL(udp_memory_allocated);++#define PORTS_PER_CHAIN (65536 / UDP_HTABLE_SIZE)++static int udp_lib_lport_inuse(struct net *net, __u16 num,+			       const struct udp_hslot *hslot,+			       unsigned long *bitmap,+			       struct sock *sk,+			       int (*saddr_comp)(const struct sock *sk1,+						 const struct sock *sk2))+{+	struct sock *sk2;+	struct hlist_nulls_node *node;++	sk_nulls_for_each(sk2, node, &hslot->head)+		if (net_eq(sock_net(sk2), net)			&&+		    sk2 != sk					&&+		    (bitmap || sk2->sk_hash == num)		&&+		    (!sk2->sk_reuse || !sk->sk_reuse)		&&+		    (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if+			|| sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&+		    (*saddr_comp)(sk, sk2)) {+			if (bitmap)+				__set_bit(sk2->sk_hash / UDP_HTABLE_SIZE,+					  bitmap);+			else+				return 1;+		}+	return 0;+}++/**+ *  udp_lib_get_port  -  UDP/-Lite port lookup for IPv4 and IPv6+ *+ *  @sk:          socket struct in question+ *  @snum:        port number to look up+ *  @saddr_comp:  AF-dependent comparison of bound local IP addresses+ */+int udp_lib_get_port(struct sock *sk, unsigned short snum,+		       int (*saddr_comp)(const struct sock *sk1,+					 const struct sock *sk2 )    )+{+	struct udp_hslot *hslot;+	struct udp_table *udptable = sk->sk_prot->h.udp_table;+	int    error = 1;+	struct net *net = sock_net(sk);++	if (!snum) {+		int low, high, remaining;+		unsigned rand;+		unsigned short first, last;+		DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN);++		inet_get_local_port_range(&low, &high);+		remaining = (high - low) + 1;++		rand = net_random();+		first = (((u64)rand * remaining) >> 32) + low;+		/*+		 * force rand to be an odd multiple of UDP_HTABLE_SIZE+		 */+		rand = (rand | 1) * UDP_HTABLE_SIZE;+		for (last = first + UDP_HTABLE_SIZE; first != last; first++) {+			hslot = &udptable->hash[udp_hashfn(net, first)];+			bitmap_zero(bitmap, PORTS_PER_CHAIN);+			spin_lock_bh(&hslot->lock);+			udp_lib_lport_inuse(net, snum, hslot, bitmap, sk,+					    saddr_comp);++			snum = first;+			/*+			 * Iterate on all possible values of snum for this hash.+			 * Using steps of an odd multiple of UDP_HTABLE_SIZE+			 * give us randomization and full range coverage.+			 */+			do {+				if (low <= snum && snum <= high &&+				    !test_bit(snum / UDP_HTABLE_SIZE, bitmap))+					goto found;+				snum += rand;+			} while (snum != first);+			spin_unlock_bh(&hslot->lock);+		}+		goto fail;+	} else {+		hslot = &udptable->hash[udp_hashfn(net, snum)];+		spin_lock_bh(&hslot->lock);+		if (udp_lib_lport_inuse(net, snum, hslot, NULL, sk, saddr_comp))+			goto fail_unlock;+	}+found:+	inet_sk(sk)->num = snum;+	sk->sk_hash = snum;+	if (sk_unhashed(sk)) {+		sk_nulls_add_node_rcu(sk, &hslot->head);+		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);+	}+	error = 0;+fail_unlock:+	spin_unlock_bh(&hslot->lock);+fail:+	return error;+}++static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)+{+	struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);++	return 	( !ipv6_only_sock(sk2)  &&+		  (!inet1->rcv_saddr || !inet2->rcv_saddr ||+		   inet1->rcv_saddr == inet2->rcv_saddr      ));+}++int udp_v4_get_port(struct sock *sk, unsigned short snum)+{+	return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal);+}++static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr,+			 unsigned short hnum,+			 __be16 sport, __be32 daddr, __be16 dport, int dif)+{+	int score = -1;++	if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&+			!ipv6_only_sock(sk)) {+		struct inet_sock *inet = inet_sk(sk);++		score = (sk->sk_family == PF_INET ? 1 : 0);+		if (inet->rcv_saddr) {+			if (inet->rcv_saddr != daddr)+				return -1;+			score += 2;+		}+		if (inet->daddr) {+			if (inet->daddr != saddr)+				return -1;+			score += 2;+		}+		if (inet->dport) {+			if (inet->dport != sport)+				return -1;+			score += 2;+		}+		if (sk->sk_bound_dev_if) {+			if (sk->sk_bound_dev_if != dif)+				return -1;+			score += 2;+		}+	}+	return score;+}++/* UDP is nearly always wildcards out the wazoo, it makes no sense to try+ * harder than this. -DaveM+ */+static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,+		__be16 sport, __be32 daddr, __be16 dport,+		int dif, struct udp_table *udptable)+{+	struct sock *sk, *result;+	struct hlist_nulls_node *node;+	unsigned short hnum = ntohs(dport);+	unsigned int hash = udp_hashfn(net, hnum);+	struct udp_hslot *hslot = &udptable->hash[hash];+	int score, badness;++	rcu_read_lock();+begin:+	result = NULL;+	badness = -1;+	sk_nulls_for_each_rcu(sk, node, &hslot->head) {+		score = compute_score(sk, net, saddr, hnum, sport,+				      daddr, dport, dif);+		if (score > badness) {+			result = sk;+			badness = score;+		}+	}+	/*+	 * if the nulls value we got at the end of this lookup is+	 * not the expected one, we must restart lookup.+	 * We probably met an item that was moved to another chain.+	 */+	if (get_nulls_value(node) != hash)+		goto begin;++	if (result) {+		if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt)))+			result = NULL;+		else if (unlikely(compute_score(result, net, saddr, hnum, sport,+				  daddr, dport, dif) < badness)) {+			sock_put(result);+			goto begin;+		}+	}+	rcu_read_unlock();+	return result;+}++static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,+						 __be16 sport, __be16 dport,+						 struct udp_table *udptable)+{+	struct sock *sk;+	const struct iphdr *iph = ip_hdr(skb);++	if (unlikely(sk = skb_steal_sock(skb)))+		return sk;+	else+		return __udp4_lib_lookup(dev_net(skb->dst->dev), iph->saddr, sport,+					 iph->daddr, dport, inet_iif(skb),+					 udptable);+}++struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,+			     __be32 daddr, __be16 dport, int dif)+{+	return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table);+}+EXPORT_SYMBOL_GPL(udp4_lib_lookup);++static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk,+					     __be16 loc_port, __be32 loc_addr,+					     __be16 rmt_port, __be32 rmt_addr,+					     int dif)+{+	struct hlist_nulls_node *node;+	struct sock *s = sk;+	unsigned short hnum = ntohs(loc_port);++	sk_nulls_for_each_from(s, node) {+		struct inet_sock *inet = inet_sk(s);++		if (!net_eq(sock_net(s), net)				||+		    s->sk_hash != hnum					||+		    (inet->daddr && inet->daddr != rmt_addr)		||+		    (inet->dport != rmt_port && inet->dport)		||+		    (inet->rcv_saddr && inet->rcv_saddr != loc_addr)	||+		    ipv6_only_sock(s)					||+		    (s->sk_bound_dev_if && s->sk_bound_dev_if != dif))+			continue;+		if (!ip_mc_sf_allow(s, loc_addr, rmt_addr, dif))+			continue;+		goto found;+	}+	s = NULL;+found:+	return s;+}++/*+ * This routine is called by the ICMP module when it gets some+ * sort of error condition.  If err < 0 then the socket should+ * be closed and the error returned to the user.  If err > 0+ * it's just the icmp type << 8 | icmp code.+ * Header points to the ip header of the error packet. We move+ * on past this. Then (as it used to claim before adjustment)+ * header points to the first 8 bytes of the udp header.  We need+ * to find the appropriate port.+ */++void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)+{+	struct inet_sock *inet;+	struct iphdr *iph = (struct iphdr*)skb->data;+	struct udphdr *uh = (struct udphdr*)(skb->data+(iph->ihl<<2));+	const int type = icmp_hdr(skb)->type;+	const int code = icmp_hdr(skb)->code;+	struct sock *sk;+	int harderr;+	int err;+	struct net *net = dev_net(skb->dev);++	sk = __udp4_lib_lookup(net, iph->daddr, uh->dest,+			iph->saddr, uh->source, skb->dev->ifindex, udptable);+	if (sk == NULL) {+		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);+		return;	/* No socket for error */+	}++	err = 0;+	harderr = 0;+	inet = inet_sk(sk);++	switch (type) {+	default:+	case ICMP_TIME_EXCEEDED:+		err = EHOSTUNREACH;+		break;+	case ICMP_SOURCE_QUENCH:+		goto out;+	case ICMP_PARAMETERPROB:+		err = EPROTO;+		harderr = 1;+		break;+	case ICMP_DEST_UNREACH:+		if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */+			if (inet->pmtudisc != IP_PMTUDISC_DONT) {+				err = EMSGSIZE;+				harderr = 1;+				break;+			}+			goto out;+		}+		err = EHOSTUNREACH;+		if (code <= NR_ICMP_UNREACH) {+			harderr = icmp_err_convert[code].fatal;+			err = icmp_err_convert[code].errno;+		}+		break;+	}++	/*+	 *      RFC1122: OK.  Passes ICMP errors back to application, as per+	 *	4.1.3.3.+	 */+	if (!inet->recverr) {+		if (!harderr || sk->sk_state != TCP_ESTABLISHED)+			goto out;+	} else {+		ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));+	}+	sk->sk_err = err;+	sk->sk_error_report(sk);+out:+	sock_put(sk);+}++void udp_err(struct sk_buff *skb, u32 info)+{+	__udp4_lib_err(skb, info, &udp_table);+}++/*+ * Throw away all pending data and cancel the corking. Socket is locked.+ */+void udp_flush_pending_frames(struct sock *sk)+{+	struct udp_sock *up = udp_sk(sk);++	if (up->pending) {+		up->len = 0;+		up->pending = 0;+		ip_flush_pending_frames(sk);+	}+}+EXPORT_SYMBOL(udp_flush_pending_frames);++/**+ * 	udp4_hwcsum_outgoing  -  handle outgoing HW checksumming+ * 	@sk: 	socket we are sending on+ * 	@skb: 	sk_buff containing the filled-in UDP header+ * 	        (checksum field must be zeroed out)+ */+static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,+				 __be32 src, __be32 dst, int len      )+{+	unsigned int offset;+	struct udphdr *uh = udp_hdr(skb);+	__wsum csum = 0;++	if (skb_queue_len(&sk->sk_write_queue) == 1) {+		/*+		 * Only one fragment on the socket.+		 */+		skb->csum_start = skb_transport_header(skb) - skb->head;+		skb->csum_offset = offsetof(struct udphdr, check);+		uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0);+	} else {+		/*+		 * HW-checksum won't work as there are two or more+		 * fragments on the socket so that all csums of sk_buffs+		 * should be together+		 */+		offset = skb_transport_offset(skb);+		skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);++		skb->ip_summed = CHECKSUM_NONE;++		skb_queue_walk(&sk->sk_write_queue, skb) {+			csum = csum_add(csum, skb->csum);+		}++		uh->check = csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, csum);+		if (uh->check == 0)+			uh->check = CSUM_MANGLED_0;+	}+}++/*+ * Push out all pending data as one UDP datagram. Socket is locked.+ */+static int udp_push_pending_frames(struct sock *sk)+{+	struct udp_sock  *up = udp_sk(sk);+	struct inet_sock *inet = inet_sk(sk);+	struct flowi *fl = &inet->cork.fl;+	struct sk_buff *skb;+	struct udphdr *uh;+	int err = 0;+	int is_udplite = IS_UDPLITE(sk);+	__wsum csum = 0;++	/* Grab the skbuff where UDP header space exists. */+	if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)+		goto out;++	/*+	 * Create a UDP header+	 */+	uh = udp_hdr(skb);+	uh->source = fl->fl_ip_sport;+	uh->dest = fl->fl_ip_dport;+	uh->len = htons(up->len);+	uh->check = 0;++	if (is_udplite)  				 /*     UDP-Lite      */+		csum  = udplite_csum_outgoing(sk, skb);++	else if (sk->sk_no_check == UDP_CSUM_NOXMIT) {   /* UDP csum disabled */++		skb->ip_summed = CHECKSUM_NONE;+		goto send;++	} else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */++		udp4_hwcsum_outgoing(sk, skb, fl->fl4_src,fl->fl4_dst, up->len);+		goto send;++	} else						 /*   `normal' UDP    */+		csum = udp_csum_outgoing(sk, skb);++	/* add protocol-dependent pseudo-header */+	uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len,+				      sk->sk_protocol, csum             );+	if (uh->check == 0)+		uh->check = CSUM_MANGLED_0;++send:+	err = ip_push_pending_frames(sk);+out:+	up->len = 0;+	up->pending = 0;+	if (!err)+		UDP_INC_STATS_USER(sock_net(sk),+				UDP_MIB_OUTDATAGRAMS, is_udplite);+	return err;+}++int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,+		size_t len)+{+	struct inet_sock *inet = inet_sk(sk);+	struct udp_sock *up = udp_sk(sk);+	int ulen = len;+	struct ipcm_cookie ipc;+	struct rtable *rt = NULL;+	int free = 0;+	int connected = 0;+	__be32 daddr, faddr, saddr;+	__be16 dport;+	u8  tos;+	int err, is_udplite = IS_UDPLITE(sk);+	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;+	int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);++	if (len > 0xFFFF)+		return -EMSGSIZE;++	/*+	 *	Check the flags.+	 */++	if (msg->msg_flags&MSG_OOB)	/* Mirror BSD error message compatibility */+		return -EOPNOTSUPP;++	ipc.opt = NULL;+	ipc.shtx.flags = 0;++	if (up->pending) {+		/*+		 * There are pending frames.+		 * The socket lock must be held while it's corked.+		 */+		lock_sock(sk);+		if (likely(up->pending)) {+			if (unlikely(up->pending != AF_INET)) {+				release_sock(sk);+				return -EINVAL;+			}+			goto do_append_data;+		}+		release_sock(sk);+	}+	ulen += sizeof(struct udphdr);++	/*+	 *	Get and verify the address.+	 */+	if (msg->msg_name) {+		struct sockaddr_in * usin = (struct sockaddr_in*)msg->msg_name;+		if (msg->msg_namelen < sizeof(*usin))+			return -EINVAL;+		if (usin->sin_family != AF_INET) {+			if (usin->sin_family != AF_UNSPEC)+				return -EAFNOSUPPORT;+		}++		daddr = usin->sin_addr.s_addr;+		dport = usin->sin_port;+		if (dport == 0)+			return -EINVAL;+	} else {+		if (sk->sk_state != TCP_ESTABLISHED)+			return -EDESTADDRREQ;+		daddr = inet->daddr;+		dport = inet->dport;+		/* Open fast path for connected socket.+		   Route will not be used, if at least one option is set.+		 */+		connected = 1;+	}+	ipc.addr = inet->saddr;++	ipc.oif = sk->sk_bound_dev_if;+	err = sock_tx_timestamp(msg, sk, &ipc.shtx);+	if (err)+		return err;+	if (msg->msg_controllen) {+		err = ip_cmsg_send(sock_net(sk), msg, &ipc);+		if (err)+			return err;+		if (ipc.opt)+			free = 1;+		connected = 0;+	}+	if (!ipc.opt)+		ipc.opt = inet->opt;++	saddr = ipc.addr;+	ipc.addr = faddr = daddr;++	if (ipc.opt && ipc.opt->srr) {+		if (!daddr)+			return -EINVAL;+		faddr = ipc.opt->faddr;+		connected = 0;+	}+	tos = RT_TOS(inet->tos);+	if (sock_flag(sk, SOCK_LOCALROUTE) ||+	    (msg->msg_flags & MSG_DONTROUTE) ||+	    (ipc.opt && ipc.opt->is_strictroute)) {+		tos |= RTO_ONLINK;+		connected = 0;+	}++	if (ipv4_is_multicast(daddr)) {+		if (!ipc.oif)+			ipc.oif = inet->mc_index;+		if (!saddr)+			saddr = inet->mc_addr;+		connected = 0;+	}++	if (connected)+		rt = (struct rtable*)sk_dst_check(sk, 0);++	if (rt == NULL) {+		struct flowi fl = { .oif = ipc.oif,+				    .nl_u = { .ip4_u =+					      { .daddr = faddr,+						.saddr = saddr,+						.tos = tos } },+				    .proto = sk->sk_protocol,+				    .flags = inet_sk_flowi_flags(sk),+				    .uli_u = { .ports =+					       { .sport = inet->sport,+						 .dport = dport } } };+		struct net *net = sock_net(sk);++		security_sk_classify_flow(sk, &fl);+		err = ip_route_output_flow(net, &rt, &fl, sk, 1);+		if (err) {+			if (err == -ENETUNREACH)+				IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);+			goto out;+		}++		err = -EACCES;+		if ((rt->rt_flags & RTCF_BROADCAST) &&+		    !sock_flag(sk, SOCK_BROADCAST))+			goto out;+		if (connected)+			sk_dst_set(sk, dst_clone(&rt->u.dst));+	}++	if (msg->msg_flags&MSG_CONFIRM)+		goto do_confirm;+back_from_confirm:++	saddr = rt->rt_src;+	if (!ipc.addr)+		daddr = ipc.addr = rt->rt_dst;++	lock_sock(sk);+	if (unlikely(up->pending)) {+		/* The socket is already corked while preparing it. */+		/* ... which is an evident application bug. --ANK */+		release_sock(sk);++		LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 2\n");+		err = -EINVAL;+		goto out;+	}+	/*+	 *	Now cork the socket to pend data.+	 */+	inet->cork.fl.fl4_dst = daddr;+	inet->cork.fl.fl_ip_dport = dport;+	inet->cork.fl.fl4_src = saddr;+	inet->cork.fl.fl_ip_sport = inet->sport;+	up->pending = AF_INET;++do_append_data:+	up->len += ulen;+	getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;+	err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,+			sizeof(struct udphdr), &ipc, &rt,+			corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);+	if (err)+		udp_flush_pending_frames(sk);+	else if (!corkreq)+		err = udp_push_pending_frames(sk);+	else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))+		up->pending = 0;+	release_sock(sk);++out:+	ip_rt_put(rt);+	if (free)+		kfree(ipc.opt);+	if (!err)+		return len;+	/*+	 * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space.  Reporting+	 * ENOBUFS might not be good (it's not tunable per se), but otherwise+	 * we don't have a good statistic (IpOutDiscards but it can be too many+	 * things).  We could add another new stat but at least for now that+	 * seems like overkill.+	 */+	if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {+		UDP_INC_STATS_USER(sock_net(sk),+				UDP_MIB_SNDBUFERRORS, is_udplite);+	}+	return err;++do_confirm:+	dst_confirm(&rt->u.dst);+	if (!(msg->msg_flags&MSG_PROBE) || len)+		goto back_from_confirm;+	err = 0;+	goto out;+}++int udp_sendpage(struct sock *sk, struct page *page, int offset,+		 size_t size, int flags)+{+	struct udp_sock *up = udp_sk(sk);+	int ret;++	if (!up->pending) {+		struct msghdr msg = {	.msg_flags = flags|MSG_MORE };++		/* Call udp_sendmsg to specify destination address which+		 * sendpage interface can't pass.+		 * This will succeed only when the socket is connected.+		 */+		ret = udp_sendmsg(NULL, sk, &msg, 0);+		if (ret < 0)+			return ret;+	}++	lock_sock(sk);++	if (unlikely(!up->pending)) {+		release_sock(sk);++		LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 3\n");+		return -EINVAL;+	}++	ret = ip_append_page(sk, page, offset, size, flags);+	if (ret == -EOPNOTSUPP) {+		release_sock(sk);+		return sock_no_sendpage(sk->sk_socket, page, offset,+					size, flags);+	}+	if (ret < 0) {+		udp_flush_pending_frames(sk);+		goto out;+	}++	up->len += size;+	if (!(up->corkflag || (flags&MSG_MORE)))+		ret = udp_push_pending_frames(sk);+	if (!ret)+		ret = size;+out:+	release_sock(sk);+	return ret;+}++/*+ *	IOCTL requests applicable to the UDP protocol+ */++int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)+{+	switch (cmd) {+	case SIOCOUTQ:+	{+		int amount = atomic_read(&sk->sk_wmem_alloc);+		return put_user(amount, (int __user *)arg);+	}++	case SIOCINQ:+	{+		struct sk_buff *skb;+		unsigned long amount;++		amount = 0;+		spin_lock_bh(&sk->sk_receive_queue.lock);+		skb = skb_peek(&sk->sk_receive_queue);+		if (skb != NULL) {+			/*+			 * We will only return the amount+			 * of this packet since that is all+			 * that will be read.+			 */+			amount = skb->len - sizeof(struct udphdr);+		}+		spin_unlock_bh(&sk->sk_receive_queue.lock);+		return put_user(amount, (int __user *)arg);+	}++	default:+		return -ENOIOCTLCMD;+	}++	return 0;+}++/*+ * 	This should be easy, if there is something there we+ * 	return it, otherwise we block.+ */++int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,+		size_t len, int noblock, int flags, int *addr_len)+{+	struct inet_sock *inet = inet_sk(sk);+	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;+	struct sk_buff *skb;+	unsigned int ulen, copied;+	int peeked;+	int err;+	int is_udplite = IS_UDPLITE(sk);++	/*+	 *	Check any passed addresses+	 */+	if (addr_len)+		*addr_len=sizeof(*sin);++	if (flags & MSG_ERRQUEUE)+		return ip_recv_error(sk, msg, len);++try_again:+	skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),+				  &peeked, &err);+	if (!skb)+		goto out;++	ulen = skb->len - sizeof(struct udphdr);+	copied = len;+	if (copied > ulen)+		copied = ulen;+	else if (copied < ulen)+		msg->msg_flags |= MSG_TRUNC;++	/*+	 * If checksum is needed at all, try to do it while copying the+	 * data.  If the data is truncated, or if we only want a partial+	 * coverage checksum (UDP-Lite), do it before the copy.+	 */++	if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {+		if (udp_lib_checksum_complete(skb))+			goto csum_copy_err;+	}++	if (skb_csum_unnecessary(skb))+		err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),+					      msg->msg_iov, copied       );+	else {+		err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);++		if (err == -EINVAL)+			goto csum_copy_err;+	}++	if (err)+		goto out_free;++	if (!peeked)+		UDP_INC_STATS_USER(sock_net(sk),+				UDP_MIB_INDATAGRAMS, is_udplite);++	sock_recv_timestamp(msg, sk, skb);++	/* Copy the address. */+	if (sin)+	{+		sin->sin_family = AF_INET;+		sin->sin_port = udp_hdr(skb)->source;+		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;+		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));+	}+	if (inet->cmsg_flags)+		ip_cmsg_recv(msg, skb);++	err = copied;+	if (flags & MSG_TRUNC)+		err = ulen;++out_free:+	lock_sock(sk);+	skb_free_datagram(sk, skb);+	release_sock(sk);+out:+	return err;++csum_copy_err:+	lock_sock(sk);+	if (!skb_kill_datagram(sk, skb, flags))+		UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);+	release_sock(sk);++	if (noblock)+		return -EAGAIN;+	goto try_again;+}+++int udp_disconnect(struct sock *sk, int flags)+{+	struct inet_sock *inet = inet_sk(sk);+	/*+	 *	1003.1g - break association.+	 */++	sk->sk_state = TCP_CLOSE;+	inet->daddr = 0;+	inet->dport = 0;+	sk->sk_bound_dev_if = 0;+	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))+		inet_reset_saddr(sk);++	if (!(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) {+		sk->sk_prot->unhash(sk);+		inet->sport = 0;+	}+	sk_dst_reset(sk);+	return 0;+}++void udp_lib_unhash(struct sock *sk)+{+	if (sk_hashed(sk)) {+		struct udp_table *udptable = sk->sk_prot->h.udp_table;+		unsigned int hash = udp_hashfn(sock_net(sk), sk->sk_hash);+		struct udp_hslot *hslot = &udptable->hash[hash];++		spin_lock_bh(&hslot->lock);+		if (sk_nulls_del_node_init_rcu(sk)) {+			inet_sk(sk)->num = 0;+			sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);+		}+		spin_unlock_bh(&hslot->lock);+	}+}+EXPORT_SYMBOL(udp_lib_unhash);++static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)+{+	int is_udplite = IS_UDPLITE(sk);+	int rc;++	if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) {+		/* Note that an ENOMEM error is charged twice */+		if (rc == -ENOMEM) {+			UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS,+					 is_udplite);+			atomic_inc(&sk->sk_drops);+		}+		goto drop;+	}++	return 0;++drop:+	UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);+	kfree_skb(skb);+	return -1;+}++/* returns:+ *  -1: error+ *   0: success+ *  >0: "udp encap" protocol resubmission+ *+ * Note that in the success and error cases, the skb is assumed to+ * have either been requeued or freed.+ */+int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)+{+	struct udp_sock *up = udp_sk(sk);+	int rc;+	int is_udplite = IS_UDPLITE(sk);++	/*+	 *	Charge it to the socket, dropping if the queue is full.+	 */+	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))+		goto drop;+	nf_reset(skb);++	if (up->encap_type) {+		/*+		 * This is an encapsulation socket so pass the skb to+		 * the socket's udp_encap_rcv() hook. Otherwise, just+		 * fall through and pass this up the UDP socket.+		 * up->encap_rcv() returns the following value:+		 * =0 if skb was successfully passed to the encap+		 *    handler or was discarded by it.+		 * >0 if skb should be passed on to UDP.+		 * <0 if skb should be resubmitted as proto -N+		 */++		/* if we're overly short, let UDP handle it */+		if (skb->len > sizeof(struct udphdr) &&+		    up->encap_rcv != NULL) {+			int ret;++			ret = (*up->encap_rcv)(sk, skb);+			if (ret <= 0) {+				UDP_INC_STATS_BH(sock_net(sk),+						 UDP_MIB_INDATAGRAMS,+						 is_udplite);+				return -ret;+			}+		}++		/* FALLTHROUGH -- it's a UDP Packet */+	}++	/*+	 * 	UDP-Lite specific tests, ignored on UDP sockets+	 */+	if ((is_udplite & UDPLITE_RECV_CC)  &&  UDP_SKB_CB(skb)->partial_cov) {++		/*+		 * MIB statistics other than incrementing the error count are+		 * disabled for the following two types of errors: these depend+		 * on the application settings, not on the functioning of the+		 * protocol stack as such.+		 *+		 * RFC 3828 here recommends (sec 3.3): "There should also be a+		 * way ... to ... at least let the receiving application block+		 * delivery of packets with coverage values less than a value+		 * provided by the application."+		 */+		if (up->pcrlen == 0) {          /* full coverage was set  */+			LIMIT_NETDEBUG(KERN_WARNING "UDPLITE: partial coverage "+				"%d while full coverage %d requested\n",+				UDP_SKB_CB(skb)->cscov, skb->len);+			goto drop;+		}+		/* The next case involves violating the min. coverage requested+		 * by the receiver. This is subtle: if receiver wants x and x is+		 * greater than the buffersize/MTU then receiver will complain+		 * that it wants x while sender emits packets of smaller size y.+		 * Therefore the above ...()->partial_cov statement is essential.+		 */+		if (UDP_SKB_CB(skb)->cscov  <  up->pcrlen) {+			LIMIT_NETDEBUG(KERN_WARNING+				"UDPLITE: coverage %d too small, need min %d\n",+				UDP_SKB_CB(skb)->cscov, up->pcrlen);+			goto drop;+		}+	}++	if (sk->sk_filter) {+		if (udp_lib_checksum_complete(skb))+			goto drop;+	}++	rc = 0;++	bh_lock_sock(sk);+	if (!sock_owned_by_user(sk))+		rc = __udp_queue_rcv_skb(sk, skb);+	else+		sk_add_backlog(sk, skb);+	bh_unlock_sock(sk);++	return rc;++drop:+	UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);+	kfree_skb(skb);+	return -1;+}++/*+ *	Multicasts and broadcasts go to each listener.+ *+ *	Note: called only from the BH handler context,+ *	so we don't need to lock the hashes.+ */+static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,+				    struct udphdr  *uh,+				    __be32 saddr, __be32 daddr,+				    struct udp_table *udptable)+{+	struct sock *sk;+	struct udp_hslot *hslot = &udptable->hash[udp_hashfn(net, ntohs(uh->dest))];+	int dif;++	spin_lock(&hslot->lock);+	sk = sk_nulls_head(&hslot->head);+	dif = skb->dev->ifindex;+	sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif);+	if (sk) {+		struct sock *sknext = NULL;++		do {+			struct sk_buff *skb1 = skb;++			sknext = udp_v4_mcast_next(net, sk_nulls_next(sk), uh->dest,+						   daddr, uh->source, saddr,+						   dif);+			if (sknext)+				skb1 = skb_clone(skb, GFP_ATOMIC);++			if (skb1) {+				int ret = udp_queue_rcv_skb(sk, skb1);+				if (ret > 0)+					/* we should probably re-process instead+					 * of dropping packets here. */+					kfree_skb(skb1);+			}+			sk = sknext;+		} while (sknext);+	} else+		consume_skb(skb);+	spin_unlock(&hslot->lock);+	return 0;+}++/* Initialize UDP checksum. If exited with zero value (success),+ * CHECKSUM_UNNECESSARY means, that no more checks are required.+ * Otherwise, csum completion requires chacksumming packet body,+ * including udp header and folding it to skb->csum.+ */+static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,+				 int proto)+{+	const struct iphdr *iph;+	int err;++	UDP_SKB_CB(skb)->partial_cov = 0;+	UDP_SKB_CB(skb)->cscov = skb->len;++	if (proto == IPPROTO_UDPLITE) {+		err = udplite_checksum_init(skb, uh);+		if (err)+			return err;+	}++	iph = ip_hdr(skb);+	if (uh->check == 0) {+		skb->ip_summed = CHECKSUM_UNNECESSARY;+	} else if (skb->ip_summed == CHECKSUM_COMPLETE) {+	       if (!csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,+				      proto, skb->csum))+			skb->ip_summed = CHECKSUM_UNNECESSARY;+	}+	if (!skb_csum_unnecessary(skb))+		skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,+					       skb->len, proto, 0);+	/* Probably, we should checksum udp header (it should be in cache+	 * in any case) and data in tiny packets (< rx copybreak).+	 */++	return 0;+}++/*+ *	All we need to do is get the socket, and then do a checksum.+ */++int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,+		   int proto)+{+	struct sock *sk;+	struct udphdr *uh;+	unsigned short ulen;+	struct rtable *rt = (struct rtable*)skb->dst;+	__be32 saddr, daddr;+	struct net *net = dev_net(skb->dev);++	/*+	 *  Validate the packet.+	 */+	if (!pskb_may_pull(skb, sizeof(struct udphdr)))+		goto drop;		/* No space for header. */++	uh   = udp_hdr(skb);+	ulen = ntohs(uh->len);+	if (ulen > skb->len)+		goto short_packet;++	if (proto == IPPROTO_UDP) {+		/* UDP validates ulen. */+		if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))+			goto short_packet;+		uh = udp_hdr(skb);+	}++	if (udp4_csum_init(skb, uh, proto))+		goto csum_error;++	saddr = ip_hdr(skb)->saddr;+	daddr = ip_hdr(skb)->daddr;++	if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))+		return __udp4_lib_mcast_deliver(net, skb, uh,+				saddr, daddr, udptable);++	sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);++	if (sk != NULL) {+		int ret = udp_queue_rcv_skb(sk, skb);+		sock_put(sk);++		/* a return value > 0 means to resubmit the input, but+		 * it wants the return to be -protocol, or 0+		 */+		if (ret > 0)+			return -ret;+		return 0;+	}++	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))+		goto drop;+	nf_reset(skb);++	/* No socket. Drop packet silently, if checksum is wrong */+	if (udp_lib_checksum_complete(skb))+		goto csum_error;++	UDP_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);+	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);++	/*+	 * Hmm.  We got an UDP packet to a port to which we+	 * don't wanna listen.  Ignore it.+	 */+	kfree_skb(skb);+	return 0;++short_packet:+	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %pI4:%u %d/%d to %pI4:%u\n",+		       proto == IPPROTO_UDPLITE ? "-Lite" : "",+		       &saddr,+		       ntohs(uh->source),+		       ulen,+		       skb->len,+		       &daddr,+		       ntohs(uh->dest));+	goto drop;++csum_error:+	/*+	 * RFC1122: OK.  Discards the bad packet silently (as far as+	 * the network is concerned, anyway) as per 4.1.3.4 (MUST).+	 */+	LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %pI4:%u to %pI4:%u ulen %d\n",+		       proto == IPPROTO_UDPLITE ? "-Lite" : "",+		       &saddr,+		       ntohs(uh->source),+		       &daddr,+		       ntohs(uh->dest),+		       ulen);+drop:+	UDP_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);+	kfree_skb(skb);+	return 0;+}++int udp_rcv(struct sk_buff *skb)+{+	return __udp4_lib_rcv(skb, &udp_table, IPPROTO_UDP);+}++void udp_destroy_sock(struct sock *sk)+{+	lock_sock(sk);+	udp_flush_pending_frames(sk);+	release_sock(sk);+}++/*+ *	Socket option code for UDP+ */+int udp_lib_setsockopt(struct sock *sk, int level, int optname,+		       char __user *optval, int optlen,+		       int (*push_pending_frames)(struct sock *))+{+	struct udp_sock *up = udp_sk(sk);+	int val;+	int err = 0;+	int is_udplite = IS_UDPLITE(sk);++	if (optlen<sizeof(int))+		return -EINVAL;++	if (get_user(val, (int __user *)optval))+		return -EFAULT;++	switch (optname) {+	case UDP_CORK:+		if (val != 0) {+			up->corkflag = 1;+		} else {+			up->corkflag = 0;+			lock_sock(sk);+			(*push_pending_frames)(sk);+			release_sock(sk);+		}+		break;++	case UDP_ENCAP:+		switch (val) {+		case 0:+		case UDP_ENCAP_ESPINUDP:+		case UDP_ENCAP_ESPINUDP_NON_IKE:+			up->encap_rcv = xfrm4_udp_encap_rcv;+			/* FALLTHROUGH */+		case UDP_ENCAP_L2TPINUDP:+			up->encap_type = val;+			break;+		default:+			err = -ENOPROTOOPT;+			break;+		}+		break;++	/*+	 * 	UDP-Lite's partial checksum coverage (RFC 3828).+	 */+	/* The sender sets actual checksum coverage length via this option.+	 * The case coverage > packet length is handled by send module. */+	case UDPLITE_SEND_CSCOV:+		if (!is_udplite)         /* Disable the option on UDP sockets */+			return -ENOPROTOOPT;+		if (val != 0 && val < 8) /* Illegal coverage: use default (8) */+			val = 8;+		else if (val > USHORT_MAX)+			val = USHORT_MAX;+		up->pcslen = val;+		up->pcflag |= UDPLITE_SEND_CC;+		break;++	/* The receiver specifies a minimum checksum coverage value. To make+	 * sense, this should be set to at least 8 (as done below). If zero is+	 * used, this again means full checksum coverage.                     */+	case UDPLITE_RECV_CSCOV:+		if (!is_udplite)         /* Disable the option on UDP sockets */+			return -ENOPROTOOPT;+		if (val != 0 && val < 8) /* Avoid silly minimal values.       */+			val = 8;+		else if (val > USHORT_MAX)+			val = USHORT_MAX;+		up->pcrlen = val;+		up->pcflag |= UDPLITE_RECV_CC;+		break;++	default:+		err = -ENOPROTOOPT;+		break;+	}++	return err;+}++int udp_setsockopt(struct sock *sk, int level, int optname,+		   char __user *optval, int optlen)+{+	if (level == SOL_UDP  ||  level == SOL_UDPLITE)+		return udp_lib_setsockopt(sk, level, optname, optval, optlen,+					  udp_push_pending_frames);+	return ip_setsockopt(sk, level, optname, optval, optlen);+}++#ifdef CONFIG_COMPAT+int compat_udp_setsockopt(struct sock *sk, int level, int optname,+			  char __user *optval, int optlen)+{+	if (level == SOL_UDP  ||  level == SOL_UDPLITE)+		return udp_lib_setsockopt(sk, level, optname, optval, optlen,+					  udp_push_pending_frames);+	return compat_ip_setsockopt(sk, level, optname, optval, optlen);+}+#endif++int udp_lib_getsockopt(struct sock *sk, int level, int optname,+		       char __user *optval, int __user *optlen)+{+	struct udp_sock *up = udp_sk(sk);+	int val, len;++	if (get_user(len,optlen))+		return -EFAULT;++	len = min_t(unsigned int, len, sizeof(int));++	if (len < 0)+		return -EINVAL;++	switch (optname) {+	case UDP_CORK:+		val = up->corkflag;+		break;++	case UDP_ENCAP:+		val = up->encap_type;+		break;++	/* The following two cannot be changed on UDP sockets, the return is+	 * always 0 (which corresponds to the full checksum coverage of UDP). */+	case UDPLITE_SEND_CSCOV:+		val = up->pcslen;+		break;++	case UDPLITE_RECV_CSCOV:+		val = up->pcrlen;+		break;++	default:+		return -ENOPROTOOPT;+	}++	if (put_user(len, optlen))+		return -EFAULT;+	if (copy_to_user(optval, &val,len))+		return -EFAULT;+	return 0;+}++int udp_getsockopt(struct sock *sk, int level, int optname,+		   char __user *optval, int __user *optlen)+{+	if (level == SOL_UDP  ||  level == SOL_UDPLITE)+		return udp_lib_getsockopt(sk, level, optname, optval, optlen);+	return ip_getsockopt(sk, level, optname, optval, optlen);+}++#ifdef CONFIG_COMPAT+int compat_udp_getsockopt(struct sock *sk, int level, int optname,+				 char __user *optval, int __user *optlen)+{+	if (level == SOL_UDP  ||  level == SOL_UDPLITE)+		return udp_lib_getsockopt(sk, level, optname, optval, optlen);+	return compat_ip_getsockopt(sk, level, optname, optval, optlen);+}+#endif+/**+ * 	udp_poll - wait for a UDP event.+ *	@file - file struct+ *	@sock - socket+ *	@wait - poll table+ *+ *	This is same as datagram poll, except for the special case of+ *	blocking sockets. If application is using a blocking fd+ *	and a packet with checksum error is in the queue;+ *	then it could get return from select indicating data available+ *	but then block when reading it. Add special case code+ *	to work around these arguably broken applications.+ */+unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)+{+	unsigned int mask = datagram_poll(file, sock, wait);+	struct sock *sk = sock->sk;+	int 	is_lite = IS_UDPLITE(sk);++	/* Check for false positives due to checksum errors */+	if ( (mask & POLLRDNORM) &&+	     !(file->f_flags & O_NONBLOCK) &&+	     !(sk->sk_shutdown & RCV_SHUTDOWN)){+		struct sk_buff_head *rcvq = &sk->sk_receive_queue;+		struct sk_buff *skb;++		spin_lock_bh(&rcvq->lock);+		while ((skb = skb_peek(rcvq)) != NULL &&+		       udp_lib_checksum_complete(skb)) {+			UDP_INC_STATS_BH(sock_net(sk),+					UDP_MIB_INERRORS, is_lite);+			__skb_unlink(skb, rcvq);+			kfree_skb(skb);+		}+		spin_unlock_bh(&rcvq->lock);++		/* nothing to see, move along */+		if (skb == NULL)+			mask &= ~(POLLIN | POLLRDNORM);+	}++	return mask;++}++struct proto udp_prot = {+	.name		   = "UDP",+	.owner		   = THIS_MODULE,+	.close		   = udp_lib_close,+	.connect	   = ip4_datagram_connect,+	.disconnect	   = udp_disconnect,+	.ioctl		   = udp_ioctl,+	.destroy	   = udp_destroy_sock,+	.setsockopt	   = udp_setsockopt,+	.getsockopt	   = udp_getsockopt,+	.sendmsg	   = udp_sendmsg,+	.recvmsg	   = udp_recvmsg,+	.sendpage	   = udp_sendpage,+	.backlog_rcv	   = __udp_queue_rcv_skb,+	.hash		   = udp_lib_hash,+	.unhash		   = udp_lib_unhash,+	.get_port	   = udp_v4_get_port,+	.memory_allocated  = &udp_memory_allocated,+	.sysctl_mem	   = sysctl_udp_mem,+	.sysctl_wmem	   = &sysctl_udp_wmem_min,+	.sysctl_rmem	   = &sysctl_udp_rmem_min,+	.obj_size	   = sizeof(struct udp_sock),+	.slab_flags	   = SLAB_DESTROY_BY_RCU,+	.h.udp_table	   = &udp_table,+#ifdef CONFIG_COMPAT+	.compat_setsockopt = compat_udp_setsockopt,+	.compat_getsockopt = compat_udp_getsockopt,+#endif+};++/* ------------------------------------------------------------------------ */+#ifdef CONFIG_PROC_FS++static struct sock *udp_get_first(struct seq_file *seq, int start)+{+	struct sock *sk;+	struct udp_iter_state *state = seq->private;+	struct net *net = seq_file_net(seq);++	for (state->bucket = start; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {+		struct hlist_nulls_node *node;+		struct udp_hslot *hslot = &state->udp_table->hash[state->bucket];+		spin_lock_bh(&hslot->lock);+		sk_nulls_for_each(sk, node, &hslot->head) {+			if (!net_eq(sock_net(sk), net))+				continue;+			if (sk->sk_family == state->family)+				goto found;+		}+		spin_unlock_bh(&hslot->lock);+	}+	sk = NULL;+found:+	return sk;+}++static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)+{+	struct udp_iter_state *state = seq->private;+	struct net *net = seq_file_net(seq);++	do {+		sk = sk_nulls_next(sk);+	} while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family));++	if (!sk) {+		if (state->bucket < UDP_HTABLE_SIZE)+			spin_unlock_bh(&state->udp_table->hash[state->bucket].lock);+		return udp_get_first(seq, state->bucket + 1);+	}+	return sk;+}++static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos)+{+	struct sock *sk = udp_get_first(seq, 0);++	if (sk)+		while (pos && (sk = udp_get_next(seq, sk)) != NULL)+			--pos;+	return pos ? NULL : sk;+}++static void *udp_seq_start(struct seq_file *seq, loff_t *pos)+{+	struct udp_iter_state *state = seq->private;+	state->bucket = UDP_HTABLE_SIZE;++	return *pos ? udp_get_idx(seq, *pos-1) : SEQ_START_TOKEN;+}++static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)+{+	struct sock *sk;++	if (v == SEQ_START_TOKEN)+		sk = udp_get_idx(seq, 0);+	else+		sk = udp_get_next(seq, v);++	++*pos;+	return sk;+}++static void udp_seq_stop(struct seq_file *seq, void *v)+{+	struct udp_iter_state *state = seq->private;++	if (state->bucket < UDP_HTABLE_SIZE)+		spin_unlock_bh(&state->udp_table->hash[state->bucket].lock);+}++static int udp_seq_open(struct inode *inode, struct file *file)+{+	struct udp_seq_afinfo *afinfo = PDE(inode)->data;+	struct udp_iter_state *s;+	int err;++	err = seq_open_net(inode, file, &afinfo->seq_ops,+			   sizeof(struct udp_iter_state));+	if (err < 0)+		return err;++	s = ((struct seq_file *)file->private_data)->private;+	s->family		= afinfo->family;+	s->udp_table		= afinfo->udp_table;+	return err;+}++/* ------------------------------------------------------------------------ */+int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo)+{+	struct proc_dir_entry *p;+	int rc = 0;++	afinfo->seq_fops.open		= udp_seq_open;+	afinfo->seq_fops.read		= seq_read;+	afinfo->seq_fops.llseek		= seq_lseek;+	afinfo->seq_fops.release	= seq_release_net;++	afinfo->seq_ops.start		= udp_seq_start;+	afinfo->seq_ops.next		= udp_seq_next;+	afinfo->seq_ops.stop		= udp_seq_stop;++	p = proc_create_data(afinfo->name, S_IRUGO, net->proc_net,+			     &afinfo->seq_fops, afinfo);+	if (!p)+		rc = -ENOMEM;+	return rc;+}++void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo)+{+	proc_net_remove(net, afinfo->name);+}++/* ------------------------------------------------------------------------ */+static void udp4_format_sock(struct sock *sp, struct seq_file *f,+		int bucket, int *len)+{+	struct inet_sock *inet = inet_sk(sp);+	__be32 dest = inet->daddr;+	__be32 src  = inet->rcv_saddr;+	__u16 destp	  = ntohs(inet->dport);+	__u16 srcp	  = ntohs(inet->sport);++	seq_printf(f, "%4d: %08X:%04X %08X:%04X"+		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d%n",+		bucket, src, srcp, dest, destp, sp->sk_state,+		atomic_read(&sp->sk_wmem_alloc),+		atomic_read(&sp->sk_rmem_alloc),+		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),+		atomic_read(&sp->sk_refcnt), sp,+		atomic_read(&sp->sk_drops), len);+}++int udp4_seq_show(struct seq_file *seq, void *v)+{+	if (v == SEQ_START_TOKEN)+		seq_printf(seq, "%-127s\n",+			   "  sl  local_address rem_address   st tx_queue "+			   "rx_queue tr tm->when retrnsmt   uid  timeout "+			   "inode ref pointer drops");+	else {+		struct udp_iter_state *state = seq->private;+		int len;++		udp4_format_sock(v, seq, state->bucket, &len);+		seq_printf(seq, "%*s\n", 127 - len ,"");+	}+	return 0;+}++/* ------------------------------------------------------------------------ */+static struct udp_seq_afinfo udp4_seq_afinfo = {+	.name		= "udp",+	.family		= AF_INET,+	.udp_table	= &udp_table,+	.seq_fops	= {+		.owner	=	THIS_MODULE,+	},+	.seq_ops	= {+		.show		= udp4_seq_show,+	},+};++static int udp4_proc_init_net(struct net *net)+{+	return udp_proc_register(net, &udp4_seq_afinfo);+}++static void udp4_proc_exit_net(struct net *net)+{+	udp_proc_unregister(net, &udp4_seq_afinfo);+}++static struct pernet_operations udp4_net_ops = {+	.init = udp4_proc_init_net,+	.exit = udp4_proc_exit_net,+};++int __init udp4_proc_init(void)+{+	return register_pernet_subsys(&udp4_net_ops);+}++void udp4_proc_exit(void)+{+	unregister_pernet_subsys(&udp4_net_ops);+}+#endif /* CONFIG_PROC_FS */++void __init udp_table_init(struct udp_table *table)+{+	int i;++	for (i = 0; i < UDP_HTABLE_SIZE; i++) {+		INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i);+		spin_lock_init(&table->hash[i].lock);+	}+}++void __init udp_init(void)+{+	unsigned long nr_pages, limit;++	udp_table_init(&udp_table);+	/* Set the pressure threshold up by the same strategy of TCP. It is a+	 * fraction of global memory that is up to 1/2 at 256 MB, decreasing+	 * toward zero with the amount of memory, with a floor of 128 pages.+	 */+	nr_pages = totalram_pages - totalhigh_pages;+	limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);+	limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);+	limit = max(limit, 128UL);+	sysctl_udp_mem[0] = limit / 4 * 3;+	sysctl_udp_mem[1] = limit;+	sysctl_udp_mem[2] = sysctl_udp_mem[0] * 2;++	sysctl_udp_rmem_min = SK_MEM_QUANTUM;+	sysctl_udp_wmem_min = SK_MEM_QUANTUM;+}++EXPORT_SYMBOL(udp_disconnect);+EXPORT_SYMBOL(udp_ioctl);+EXPORT_SYMBOL(udp_prot);+EXPORT_SYMBOL(udp_sendmsg);+EXPORT_SYMBOL(udp_lib_getsockopt);+EXPORT_SYMBOL(udp_lib_setsockopt);+EXPORT_SYMBOL(udp_poll);+EXPORT_SYMBOL(udp_lib_get_port);++#ifdef CONFIG_PROC_FS+EXPORT_SYMBOL(udp_proc_register);+EXPORT_SYMBOL(udp_proc_unregister);+#endif
 |